Forum: Ruby In Depth: attr_reader/writer/accessor

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Matthew M. (Guest)
on 2008-11-23 23:50
Can anyone explain exactly what happens when the interpreter interprets
attr_reader and its kin?

E.G. where is the method located (in which module, class) and what does
it do with the symbols in order to expand the method call into an
instance method of the calling class object?
Michael G. (Guest)
on 2008-11-24 00:32
(Received via mailing list)
On Sun, Nov 23, 2008 at 4:45 PM, Matthew M. 
<removed_email_address@domain.invalid>
wrote:
> Can anyone explain exactly what happens when the interpreter interprets
> attr_reader and its kin?
>
> E.G. where is the method located (in which module, class) and what does
> it do with the symbols in order to expand the method call into an
> instance method of the calling class object?

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

HTH
Michael G.
Gregory B. (Guest)
on 2008-11-24 01:04
(Received via mailing list)
Not an answer to the OP's question, but...

On Sun, Nov 23, 2008 at 5:27 PM, Michael G. 
<removed_email_address@domain.invalid>
wrote:
> On Sun, Nov 23, 2008 at 4:45 PM, Matthew M. <removed_email_address@domain.invalid> 
wrote:

> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

This implementation:

> def new_attr_reader cl, sym
>   str = "def #{sym.to_s}; @#{sym.to_s}; end"
>   cl.class_eval str
> end

is more dangerous than it needs to be.  Instead, you can write:

def new_attr_reader(*args)
  args.each { |e| define_method(e) { instance_variable_get("@#{e}") } }
end

Which allows for:

class A
  new_attr_reader :a, :b, :c

  def initialize
    @a = 1
    @b = 2
    @c = 3
  end
end

a = A.new
p [a.a, a.b, a.c] #=> [1, 2, 3]

Of course, substitute instance_variable_set for writers.
David A. Black (Guest)
on 2008-11-24 10:44
(Received via mailing list)
Hi --

On Mon, 24 Nov 2008, Matthew M. wrote:

> Can anyone explain exactly what happens when the interpreter interprets
> attr_reader and its kin?
>
> E.G. where is the method located (in which module, class) and what does
> it do with the symbols in order to expand the method call into an
> instance method of the calling class object?

attr_reader and friends are private instance methods of the class
Module:

>> Module.private_instance_methods(false).grep(/attr/)
=> ["attr_accessor", "attr_writer", "attr_reader", "attr"]

which means that as long as self is an instance of Module or one of
its subclasses, those methods can be called. The Class class is a
subclass of Module, so instances of Class can execute those methods
too. That's what's happening when you do:

   class C
     attr_accessor :x
   end

As for what it does: see Greg's Ruby implementation, and also the
original C code which is in eval.c (look for the definition of
rb_attr). It basically calls rb_define_method, which is a general
method for adding methods to classes.

I used implementing attr_* as a metaprogramming exercise in a Ruby
course I taught last week, and it was very instructive. Amazing what
you can do in Ruby, without even getting terribly convoluted or
opaque.


David
Matthew M. (Guest)
on 2008-11-24 11:03
David A. Black wrote:
> Hi --
>
> On Mon, 24 Nov 2008, Matthew M. wrote:
>
>> Can anyone explain exactly what happens when the interpreter interprets
>> attr_reader and its kin?
>>
>> E.G. where is the method located (in which module, class) and what does
>> it do with the symbols in order to expand the method call into an
>> instance method of the calling class object?
>
> attr_reader and friends are private instance methods of the class
> Module:
>
>>> Module.private_instance_methods(false).grep(/attr/)
> => ["attr_accessor", "attr_writer", "attr_reader", "attr"]
>
> which means that as long as self is an instance of Module or one of
> its subclasses, those methods can be called. The Class class is a
> subclass of Module, so instances of Class can execute those methods
> too. That's what's happening when you do:
>
>    class C
>      attr_accessor :x
>    end
>
> As for what it does: see Greg's Ruby implementation, and also the
> original C code which is in eval.c (look for the definition of
> rb_attr). It basically calls rb_define_method, which is a general
> method for adding methods to classes.
>
> I used implementing attr_* as a metaprogramming exercise in a Ruby
> course I taught last week, and it was very instructive. Amazing what
> you can do in Ruby, without even getting terribly convoluted or
> opaque.
>
>
> David

Not that I don't appreciate the other responses but this is exactly what
I was looking for. Thank you for your help everyone. Also, David, can
you recommend any reference texts for Ruby that delve into this much
detail for other similar concepts. I'm nearly finished with Programming
Ruby: Pragmatic Programmers and I feel like I want a bit more.

Thanks!
David A. Black (Guest)
on 2009-01-19 19:12
(Received via mailing list)
Hi --

On Mon, 24 Nov 2008, Matthew M. wrote:

>>> instance method of the calling class object?
>> too. That's what's happening when you do:
>> I used implementing attr_* as a metaprogramming exercise in a Ruby
> detail for other similar concepts. I'm nearly finished with Programming
> Ruby: Pragmatic Programmers and I feel like I want a bit more.

Sorry -- this got lost in the inbox pipeline. I have an answer for
you, though: <plug>The Well-Grounded Rubyist (by me), due out in
March. See http://www.manning.com/black2. There's no one-stop-shopping
source for all such stuff but I think you'll find a good bit in there.
</plug>


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

http://www.wishsight.com => Independent, social wishlist management!
This topic is locked and can not be replied to.