# Foo= methods don't get called inside instance scope without

**URL:** <https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136>\
**Category:** Ruby\
**Created:** [May 20, 2006, 8:26pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136 "2006-05-20T20:26:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 20, 2006, 8:26pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/1 "2006-05-20T20:26:56Z")

</div>

irb(main):001:0\> class Bar; def foo=(val); puts “Bar#foo= called!”; end;  
end  
irb(main):002:0\> Bar.new.instance\_eval { foo = 1 } #=\> no  
output  
irb(main):003:0\> Bar.new.instance\_eval { foo= 1 } #=\> no  
output  
irb(main):004:0\> Bar.new.instance\_eval { self.foo = 1 } #=\> Bar#foo=  
called!

It seems like the only way to call Bar#foo= inside and instance of Bar  
is by prefixing self explicitly. Am I right about this?

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 20, 2006, 8:30pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/2 "2006-05-20T20:30:08Z")

</div>

2006/5/20, Alder G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> irb(main):001:0\> class Bar; def foo=(val); puts “Bar#foo= called!”; end; end  
> irb(main):002:0\> Bar.new.instance\_eval { foo = 1 } #=\> no output  
> irb(main):003:0\> Bar.new.instance\_eval { foo= 1 } #=\> no output  
> irb(main):004:0\> Bar.new.instance\_eval { self.foo = 1 } #=\> Bar#foo= called!
> 
> It seems like the only way to call Bar#foo= inside and instance of Bar  
> is by prefixing self explicitly. Am I right about this?

Yes. foo= is a local variable assignment. See  
[http://ruby-doc.org/docs/ProgrammingRuby/html/tut\_expressions.html#S3](http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#S3)  
(you’ll have to scroll down a bit).

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 20, 2006, 8:42pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/3 "2006-05-20T20:42:17Z")

</div>

On 5/20/06, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> [Programming Ruby: The Pragmatic Programmer's Guide](http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#S3)  
> (you’ll have to scroll down a bit).
> 
> Kind regards
> 
> robert
> 
> –  
> Have a look: [Robert K. | Flickr](http://www.flickr.com/photos/fussel-foto/)

Yup. Seems like assignments to local variable take foo precedence over  
calling foo=. Kind of a shame, since I have to use self.foo= whenever  
I want to call foo=. A bit ugly. Which is why I wanted to make sure  
there’s no alternative.

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 21, 2006, 10:06am UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/4 "2006-05-21T10:06:42Z")

</div>

I’m not sure of your specific situation, but i’ve found this to help in  
these circumstances:

class Module  
def dsl\_accessor(\*symbols)  
symbols.each { |sym|  
class\_eval %{  
def #{sym}(\*val)  
if val.empty?  
@#{sym}  
else  
@#{sym} = val.size == 1 ? val[0] : val  
end  
end  
}  
}  
end  
end

Bar.dsl\_accessor :foo  
b = Bar.new.  
b.instance\_eval { foo 1 } #=\> 1  
b.instance\_eval { foo } #=\> 1

See [artima - Creating DSLs with Ruby](http://www.artima.com/rubycs/articles/ruby_as_dsl3.html) for more.

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 21, 2006, 12:07pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/5 "2006-05-21T12:07:45Z")

</div>

On 5/21/06, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> else
> 
> ```
> 
> b.instance\_eval { foo 1 } #=\> 1  
> b.instance\_eval { foo } #=\> 1
> 
> See [artima - Creating DSLs with Ruby](http://www.artima.com/rubycs/articles/ruby_as_dsl3.html) for more.

Interesting code. Unfortunately, it’s not relevant to the issue I  
raised.

That issue stems from the way the Ruby interpreter handles names. As  
you know, regular names in Ruby can be both method calls and local  
variables. Whever a name could be treated as either one of these, the  
interpreter prefers to treat it as a local variable. Example:

class Foo  
def bar  
@fred.bar  
end

def bar=(val)  
@fred.bar = val  
end

def initialize  
@fred = Struct.new(:bar).new  
end  
end

foo = Foo.new

Outside of instance foo’s scope, the accessor methods we built work as  
expected:

foo.bar = 1  
foo.instance\_eval(‘@fred.bar’) #=\> 1

However, notice what happens once we try calling them from within foo’s  
scope:

foo.instance\_eval(‘bar’) #=\> 1 – Ok so far…  
foo.instance\_eval(‘bar = 22’)  
foo #=\> #\<Foo:0x2c8bb10 @fred=#\<struct #Class:0x2c8bac8 bar=1\>\>

Whoops! @fred.baz wasn’t changed. So what was?

What happened is that the interpreter could interpret “bar = 22” in  
foo’s scope in two different ways:

1. self.bar=(22) # What we actually want
2. create local variable bar and assign to it the value 22

And since it always prefers the local variable interpretation, number  
2 is what actually happens. In fact, now even method bar doesn’t work  
within foo:

foo.instance\_eval(‘bar’) #=\> 22  
foo.instance\_eval(‘@fred.bar’) #=\> 1

Within foo, bar returns 22, but @fred.bar is still 1. That’s because  
now foo also has two possible interpretations, and the local-variable  
interpretation is again prefered, so bar returns the value of local  
variable bar.

I can see two ways to deal with this issue:

1. Always prefix foo.bar= calls with self within foo. This eliminates  
the local-variable possible interpration. However, it is kind of  
ugly, and it’s easy to introduce elusive bugs by forgetting the  
prefix.

2. Avoid using the bar= syntax. You can either use a seperate setter  
method set\_bar, or what the code you posted does (set and return bar  
to arg if supplied, just return bar otherwise).

Hope the issue is clearer 🙂

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 21, 2006, 2:43pm UTC](https://www.ruby-forum.com/t/foo-methods-dont-get-called-inside-instance-scope-without/61136/6 "2006-05-21T14:43:07Z")

</div>

2006/5/21, Alder G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I can see two ways to deal with this issue:
> 
> 1. Always prefix foo.bar= calls with self within foo. This eliminates  
> the local-variable possible interpration. However, it is kind of  
> ugly, and it’s easy to introduce elusive bugs by forgetting the  
> prefix.
> 
> 2. Avoid using the bar= syntax. You can either use a seperate setter  
> method set\_bar, or what the code you posted does (set and return bar  
> to arg if supplied, just return bar otherwise).

A nice variant of 2 makes use of the fact that a method can receive a  
hash without using curly braces:

> > class Foo  
> > def init(params)  
> > params.each {|k,v| print k,“=”,v,“\n”}  
> > end  
> > end  
> > =\> nil  
> > Foo.new.init(:name =\> “foo”, :size =\> 123)  
> > size=123  
> > name=foo  
> > =\> {:size=\>123, :name=\>“foo”}

Instead of printing you can of course use key value pairs for setting  
instance variables or invoking setters.

Kind regards

robert
