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?
# 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.
···
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?
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
···
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?
Eep, yeah, I forgot about that. #dup and #clone won't work, sorry for
that misinformation.
Jason
···
On Mon, Apr 14, 2008 at 1:43 PM, ara.t.howard <ara.t.howard@gmail.com> wrote:
On Apr 14, 2008, at 11:34 AM, Jason Roelofs wrote:
>
> # Always give a copy of the array, that way the internal @elems
> # array is never changed.
> def elems
> @elems.clone
> end
> end
>
does not work, neither does dup. both are rather shallow in ruby. if you
*really* want a copy you need
Marshal.load(Marshal.dump(@elems))
otherwise you'll end up with subtle bugs when the array is cloned, but
elements inside of it, or deeper, are not.
fyi.
a @ http://codeforpeople.com/
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama