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.