Peter Vandenabeele
Shallow string copies in Ruby
I got stung today by the shallow copies in Ruby. The problem is demonstrated in this snippet:
a="raam"; b=a ; b.squeeze!; puts a # --> ram
a="raam"; b=a ; b[0..1]="tr"; puts a # --> tram
a="raam"; b=a ; a[0..1]="tr"; puts b # --> tram
What seems to happen is that b is only a shallow copy of a. Actually, this behavior is much closer to the string behavior that I know well from C/C++ programming than I had expected for a "pointer-less" language. So, it seems still usefull to understand pointers (and strcpy for that matter), even for Ruby...
2 solutions I see are:
- use deep copy when required ... that is done with the "dup" method (similar to "clone" as Patrick suggests). For strings, I see this as the Ruby equivalent of strcpy
- be careful not to use any "in-place" modifications of a string of which a shallow copy exists
So possible ways are:
a="raam"; b=a.dup; b.squeeze!; puts a # --> raam
a="raam"; b=a; b="tr"+b[2..-1]; puts a # --> raam
These 2 lines have the intended effect on b and leave a untouched.
Anonymous wrote:
You're the second one in 2 weeks time to make this remark (the other one being the guys of passenger phusion, so you're in good company ;-) )
That behaviour can be called 'shallow'. Shallow copies are the default in OO languages. Take for example
a = Person.new
a.first_name = 'Jef'
b = a
a.first_name = 'Jos'
puts b.first_name
What do you expect to be the output? It's 'Jos', isn't it?
The only reason people think the behaviour is wrong in your example, is because Java implements a very specific behaviour for Strings: the assignment of a String in Java isn't a pure assignment. Apart from that, I don't see any reason to consider the Ruby behaviour as 'unexpected'.
-- Tom Klaasen - http://tomklaasen.net
»
Anonymous wrote:
Sorry, I'm going to partly repeat my tweets I think :-)
What you see as a "shallow copy" (sounds like a flaw) is an object assignment (and in fact very consistent OO behaviour) - strings are objects, so yes, you could compare them to pointers...
If you want a copy, you should write
b = a.clone
Pascal
http://pascal.vanhecke.info
»
peterv wrote:
This description on Wikipedia http://en.wikipedia.org/wiki/Object_copy gives a good overview of the shallow copy and deep copy techniques.
Peter
http://www.vandenabeele.com
»