# Setting default vales

**URL:** <https://www.ruby-forum.com/t/setting-default-vales/87989>\
**Category:** Ruby\
**Created:** [March 7, 2007, 10:35am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989 "2007-03-07T10:35:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 7, 2007, 10:35am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/1 "2007-03-07T10:35:43Z")

</div>

Hello,

I want to have some function that will two parameters. First is the  
variable name and second is a value.  
Inside I will check:

- if the variable is existed I do nothing
- else I assign “value” to variable

It should be something like this but it is not working.

def set\_default(name, val)  
if ! name then  
eval “#{name} = #{val}”  
end  
end

set\_default(“b”, “2”)  
puts "b = " + b

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 7, 2007, 10:56am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/2 "2007-03-07T10:56:47Z")

</div>

On 3/7/07, Mike [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def set\_default(name, val)  
> if ! name then  
> eval “#{name} = #{val}”  
> end  
> end
> 
> set\_default(“b”, “2”)  
> puts "b = " + b

The first deception will come from this little snippet I am afraid,  
cat default.rb && echo “--------------” && ruby default.rb

# vim: sts=2 sw=2 nu expandtab nowrap:

## a = 42 def test\_a defined? a end p test\_a

nil

As you can see a is not visible inside the method.  
Let us try to find a different tool for that

# vim: sts=2 sw=2 nu expandtab nowrap:

## a = 42 test\_a = proc { defined? a } p test\_a.call

“local-variable”

Which is better, we could now try to implement what you want as a proc

# vim: sts=2 sw=2 nu expandtab nowrap:

## a = 42 default = proc { |name, value| eval “defined? #{name} ? nil : #{name} = #{value}” } default.call :a, 43 default.call :b, 43 puts a puts b

42  
def\_proc.rb:9: undefined local variable or method `b’ for main:Object  
(NameError)  
What is happening here?  
Well we cannot make b spring into live _outside_ the proc scope.

This all just to ask two questions  
Why using local variables and not instance variables? look at snippet  
(1) below

Is the name ||= value syntax not good enough? I know it will overwrite  
nil and false values but more often than not it is quite good enough.

If you really need what you want you will need some help from meta  
programming gurus. If I am not mistaken this can be done with things  
like binding\_from\_caller  
as can be found in Facets, also have a look at Maurico Fernandez’ site  
[http://eigenclass.org/](http://eigenclass.org/)

HTH.  
Robert  
(1)

# vim: sts=2 sw=2 nu expandtab nowrap:

@a = 42  
def default name, value  
return if instance\_variables.include? name

# There even is instance\_variable\_exists? in

# 1.8.6

instance\_variable\_set name, value  
end  
default “@a”, 43  
default “@b”, 43  
puts @a  
puts @b

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 7, 2007, 11:11pm UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/3 "2007-03-07T23:11:16Z")

</div>

Thank you for your answer.  
But it looks like this is a real problem for Ruby to use such  
construct.  
probably there is some other way (I don’t like to use @) to solve it.  
Could I get a left side of “=” by some reference?  
For example,  
b = my\_func(def\_val)  
Could I redefine “=” and get some information on “b”? And if b is  
invalid I’ll return “def\_val” otherwise I’ll return “b” itself.

Also, can I pass a “reference”/“pointer” into function?

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 8, 2007, 12:03am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/4 "2007-03-08T00:03:23Z")

</div>

On 3/7/07, Mike [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
Please Mike try not to top post unless you need to, normally we prefer  
to post after the text one is referring to.

> Thank you for your answer.  
> But it looks like this is a real problem for Ruby to use such  
> construct.  
> probably there is some other way (I don’t like to use @) to solve it.  
> Could I get a left side of “=” by some reference?  
> For example,  
> b = my\_func(def\_val)  
> Could I redefine “=” and get some information on “b”? And if b is  
> invalid I’ll return “def\_val” otherwise I’ll return “b” itself.

Well I tried hard with Binding.of\_caller from facet but maybe I miss  
something.  
As I mentioned before I am not a metaprogramming guru ☹

> Also, can I pass a “reference”/“pointer” into function?  
> Well all parameters are passed as references - even if there is a  
> studied discussion if this terminology is 100% correct.

try e.g.  
a=“Hi there”  
def change s  
s \<\< “!!!”  
end  
change a  
puts a

> On Mar 7, 8:55 pm, “Robert D.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > On 3/7/07, Mike [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> > 
> > –

Cheers  
Robert  
We have not succeeded in answering all of our questions.  
In fact, in some ways, we are more confused than ever.  
But we feel we are confused on a higher level and about more important  
things.  
-Anonymous

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 8, 2007, 3:37am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/5 "2007-03-08T03:37:48Z")

</div>

> Well I tried hard with Binding.of\_caller from facet but maybe I miss  
> something.  
> As I mentioned before I am not a metaprogramming guru ☹

🙂

> puts a
> 
> >

Probably it works with strings but try following code:

def test\_change(var, val)  
var = val  
end

myvar = 5  
test\_change(myvar, 10)  
puts myvar.to\_s

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 8, 2007, 8:46am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/6 "2007-03-08T08:46:11Z")

</div>

On 3/8/07, Michael S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > Well all parameters are passed as references - even if there is a
> 
> Probably it works with strings but try following code:
> 
> def test\_change(var, val)  
> var = val  
> end
> 
> myvar = 5  
> test\_change(myvar, 10)  
> puts myvar.to\_s

They second I sent the mail I knew I was not precise enough ☹

Variables themselves are passed as values, stupid me how could I have  
been so imprecise.  
Only that all variables are than references to objects which can be  
changed unless they are immutable.

thy Michael and sorry for my hasty post

Robert

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 8, 2007, 10:01am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/7 "2007-03-08T10:01:20Z")

</div>

On Thu, Mar 08, 2007 at 07:10:08AM +0900, Mike wrote:

> Thank you for your answer.  
> But it looks like this is a real problem for Ruby to use such  
> construct.  
> probably there is some other way (I don’t like to use @) to solve it.  
> Could I get a left side of “=” by some reference?

Free your mind a little 🙂 Allow for the possibility that there might  
be a  
problem in how you’re approaching this, rather than how Ruby works. (I  
was  
very bad in this regard in the early days; I would dread to go back and  
find  
my early postings to ruby-talk).

In Ruby, almost everything is an object. That means: you access it via  
an  
object reference.

However, local variables are _not_ objects. You cannot take a reference  
to  
them, nor alias them. They are simply placeholders which _contain_ a  
reference to an object.

Could Ruby have been designed so that local variables were themselves  
objects? Perhaps. Why wasn’t it done? Because the Ruby approach is much  
more  
efficient. Ruby local variables are just slots in the stack frame, at a  
fixed offset, and are therefore very cheap to use.

So whilst Ruby is an extremely dynamic language - objects and classes  
can be  
created on the fly, instance variables added to and removed from  
objects,  
even methods added to objects - this doesn’t apply to local variables  
themselves, which just refer to these objects. As you’ve found, if you  
want  
to create a local variable on the fly, you have to jump through huge  
hoops.

Hence the real answer is: just don’t do it. Show us a real problem which  
involves you creating a local variable on the fly, and we’ll show you a  
much  
better way of doing it in Ruby. When you realise how easy it is to  
define  
and create objects, then you’ll find that almost certainly an object is  
the  
correct container for the state you’re trying to build, not the stack  
frame.

> Also, can I pass a “reference”/“pointer” into function?

All objects are passed by reference, even things like classes:

def make\_a(klass) # note (\*) below  
return klass.new  
end

class Foo  
def hello  
puts “hello!”  
end  
end

k = Foo  
f = make\_a(k)  
f.hello

But as I said above, a local variable isn’t an object, and you can’t  
take a  
reference to it. That is, make\_a(k) passes, by value, the object  
reference  
which k contains, not a reference to the local variable k itself.

Now, if you want to be able to change which object k points to, then  
simply  
return a new object reference:

k = change\_it(k) # after this, k can refer to a new object

But much more often in Ruby, you’ll change the state of the object  
itself:

change\_it(k) # doesn’t change which object k points to, but  
# changes the internal state of object k

or more idiomatically:

k.change\_it # now the ‘change\_it’ code is a method belonging  
# to object k, or k’s class

> > I want to have some function that will two parameters. First is the  
> > variable name and second is a value.  
> > Inside I will check:
> > 
> > - if the variable is existed I do nothing
> > - else I assign “value” to variable

The Ruby idiom for this is not to call a function, but just to write:

```
foo ||= "my_default_value"

```

This is a shorthand notation for:

```
foo = foo || "my default value"

```

The || operator returns the LHS if it is not nil or false; otherwise it  
evaluates and returns the RHS. Of course the RHS can be a complex  
expression, or a function (method) call:

```
def make_default_foo(x,y,z)
  ... return a value based on x,y,z or whatever
end

foo ||= make_default_foo(17, 4, Time.now)

```

Hope this is clear,

Brian.

(\*) All arguments to a function/method are object instances, so here  
‘klass’  
is an object instance. If you prefer, what’s passed is really a  
_reference_  
to an object instance, but you can quickly stop saying “…a reference  
to…” since this is always the case in Ruby.

The intention of this particular function is that the argument is an  
instance of a ‘Class’ object. But actually it doesn’t have to be; it  
could  
be any object which has a ‘new’ method. If you pass in any object which  
doesn’t have a ‘new’ method, you’ll get a “method missing” error at  
runtime  
when it tries to invoke this method.

---

<div class="post-metadata">

**Author:** ![mike](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58f4c7/32.png) [@mike](https://www.ruby-forum.com/u/mike)\
**Post date:** [March 8, 2007, 10:09am UTC](https://www.ruby-forum.com/t/setting-default-vales/87989/8 "2007-03-08T10:09:21Z")

</div>

On Thu, Mar 08, 2007 at 11:36:58AM +0900, Michael S. wrote:

> > 
> 
> def test\_change(var, val)  
> var = val  
> end
> 
> myvar = 5  
> test\_change(myvar, 10)  
> puts myvar.to\_s

That’s because:

(1) “\<\<” is a method call, but “=” is not (it’s an assignment to a local  
variable)

(2) Strings are mutable, but numbers are not. That is, there’s no method  
call you can make on the number ‘5’ which will change its value to  
something  
else 🙂

So you either return the new number:

def change(val)  
val + 1  
end

myvar = 5  
myvar = change(myvar)  
puts myvar

Or you wrap it in an object:

class Myvar  
attr\_accessor :v  
def initialize(v = nil)  
@v = v  
end  
def to\_s  
@v.to\_s  
end  
end

def test\_change(obj, newval)  
obj.v = newval  
end

myvar = Myvar.new(5)  
test\_change(myvar, 10)  
puts myvar.to\_s

The notation “attr\_accessor :v” is short for:

def v  
@v  
end

def v=(nv)  
@v = nv  
end

So when you write obj.v = newval, you are calling v=(newval) on the  
object.

Regards,

Brian.
