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