On Mon, Apr 14, 2008 at 1:25 PM, Adam Bender <abender / 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>] > > You misunderstand what "attr_reader" does. The "attr_" methods simply generate setter / getter methods on your class for instance variables. attr_reader :variable def variable; @variable; end attr_writer :variable def variable=(val); @variable = val; end attr_accessor :variable creates both. If you want something truely immutable, you have to #freeze it, but then it's not changeable inside the class either. If you're really worried about this, you can manually do: class Example def initialize @elems = [] 3.times { @elems << Object.new } end def to_s @elems.inspect end # Always give a copy of the array, that way the internal @elems # array is never changed. def elems @elems.clone end end Hope that helps. Jason R.