D.E., while you're technically not wrong, IMHO, the need to undef
the method is only abated in the strictest of senses: the sanity check averts what might otherwise be a segfault or memory leak or some other aberration, and makes things 'safe', but it's neither straightforward nor intuitive for the programmer, nor consistent with the implementation of similar functions in ruby.
For instance, freeze
doesn't throw any sort of similar error when you call it on an already frozen object, or even for the immediate (and therefore inherently immutable) objects you used in your demonstration.
I think the core issue Xavier is getting at here (and I took the liberty of updating the subject thusly; Xavier, if you don't feel it's a fair representation of the issue, please feel free to change it back) is that a select few object types in Ruby are immediate variables and therefore cannot be dup
ed/clone
d, yet there is no graceful/robust method of averting the error thrown by this sanity check when you attempt to dup
/clone
them. (In the source, both rb_obj_dup
and rb_obj_clone
if the object to be **dup
ed/clone
**d is a rb_special_const_p
. As far as I can tell, this method nor anything equivalent is exposed in the ruby language, however.)
I literally can't imagine any scenario in which a dev, when, say, coding a class with the line:
return val.dup.freeze
.. really wants an Exception
thrown when val
happens to be de-facto un-dup
-able. What they really want is:
return val.dup.freeze rescue val
To me it seems there are three possible solutions to this (of which any two can be implemented):
- As Xavier suggested, only define the functions for objects that will actually
dup
/clone
. (This will implicitly allow respond_to?
checks as well as not interfere with existing code that may attempt to rescue
failed attempts -- that is unless TypeError
was specified, and even that could be worked around with a bit more code.)
- Add additional methods to all objects named
dupable?
and clonable?
that return values consistent with exactly what their names suggest.
- Have these methods function exactly the way
freeze
does: fail silently. If the object can't be dup
ed/clone
d because it's an immediate, dup
/clone
should return the object itself. (There shouldn't be any harm in doing so since nothing about the object can be changed in the first place.)