From: Brian Candler Date: 2009-01-22T18:50:23+09:00 Subject: Re: String doesnt auto dup on modification RK Sentinel wrote: >> class Object >> def dupf >> frozen? ? self : dup >> end >> end >> >> and then >> >> class MyClass >> def initialize(name) >> @name = name.dupf >> end >> end >> >> Kind regards >> >> robert > > thanks, this looks very helpful. Beware: this may not solve your problem. It will work if the passed-in object is itself a String, but not if it's some other object which contains Strings. Try: a = ["hello", "world"] b = a.dupf b[0] << "XXX" p a However, deep-copy is an even less frequently seen solution. > In response to the prev post by Brian, yes its a library for use by > others. It's hard to provide concrete guidance without knowing what this library does, but it sounds like it builds some data structure which includes the string passed in. I believe that a typical library is behaving correctly if it just stores a reference to the string. If a problem arises because the caller is later mutating that string object, this could be considered to be a bug in the *caller*. The caller can fix this problem by dup'ing the string at the point when they pass it in, or dup'ing it later before changing it. Again, this is not a hard-and-fast rule. Sometimes defensive dup'ing is reasonable. For example, Ruby's Hash object has a special-case for string keys: if you pass in an unfrozen string as a hash key, then the string is dup'd and frozen before being used as the key. This may (a) lead to surprising behaviour, and (b) doesn't solve the general problem (*). However strings are very commonly used as hash keys, and they are usually short, so it seems a reasonable thing to do. Regards, Brian. (*) In the case of a hash with string keys, if you mutated one of those keys then it could end up being on the wrong hash chain, and become impossible to retrieve it from the hash using hash["key"] So it's a question of which of two behaviours is least undesirable: objects disappearing from the hash because you forgot to call #rehash, or hashes working "right" with string keys but "wrong" with other keys. irb(main):001:0> k = [1] => [1] irb(main):002:0> h = {k => 1, [2] => 2} => {[1]=>1, [2]=>2} irb(main):003:0> h[[1]] => 1 irb(main):004:0> k << 2 => [1, 2] irb(main):005:0> h => {[1, 2]=>1, [2]=>2} irb(main):006:0> h[[1,2]] => nil <<< WHOOPS! irb(main):007:0> h.rehash => {[1, 2]=>1, [2]=>2} irb(main):008:0> h[[1,2]] => 1 -- Posted via http://www.ruby-forum.com/.