On Apr 14, 11:25 am, Adam Bender <aben... / gmail.com> wrote:
> I noticed some surprising behavior in one of my Ruby programs, and am
> wondering what the rationale is.  Basically,
> given read-only access to a member variable (using attr_reader) of
> class Array, I can modify that Array by modifying (what I think should
> be) a local copy of it.  Shouldn't the accessor return a copy of the
> variable instead of a reference to it?  Or is it standard practice to
> hand-write an accessor for arrays that returns a clone of the array?
>
> #!/usr/bin/ruby
>
> class Example
>   attr_reader :elems
>
>   def initialize
>     @elems = []
>     3.times { @elems << Object.new }
>   end
>
>   def to_s
>     @elems.inspect
>   end
> end
>
> e = Example.new
> puts e
> # output is:
> # -604282308
> # [#<Object:0xb7f6c450>, #<Object:0xb7f6c43c>, #<Object:0xb7f6c428>]
>
> list = e.elems
> puts list.object_id
> # output is: -604282308
> list.delete_at(0)
>
> puts e
> # output is
> # -604282308
> # [#<Object:0xb7f6c43c>, #<Object:0xb7f6c428>]

This was recently discussed on this list. See:
http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/18058b9f36bdd1a7/

But the short answer is: Yes, you'll have to write your own accessor
if you don't want this behavior.  All attr_reader does is define the
accessor, which just returns the object.  You don't get a setter
method (elems=), but that doesn't make the object immutable.

HTH,
Chris