Issue #13634 has been reported by rovf (Ronald Fischer).

----------------------------------------
Misc #13634: NilClass is lying about respond_to?(:clone)
https://bugs.ruby-lang.org/issues/13634

* Author: rovf (Ronald Fischer)
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I put this under "Misc", because I'm not sure, whether this is a bug, a feature request, or maybe a deliberate (but for me obscure) decision in language design:

NilClass (and Fixnum) do not support clone. That's fine. However, 

   nil.respons_to?(:clone) returns true.

This means that we *can* ask nil to clone itself (we don't get a NoMethod error), it's just trying to do so throws an exception.

I stumbled over this problem when I had an collection of objects of different types, and wanted to apply :clone to some of them. My code went approximately like this:

   object = collection[key]
   return object.respond_to?(:clone) ? object.clone : object

This doesn't work, if object is nil, true, false, a Symbol or a Fixnum, because all of them claim to respond to :clone.

Of course, there is a trivial workaround (I just have to rescue the exception), but I find this language design not really intuitive. I think there are two possibilites, how this can be made better:

(1) If we decide, that nil is not clonable (because there can be only one nil), then respond_to?(:clone) should IMHO simply be false.

(2) However, there might be even be a reason why :clone should be applicable. Note that the usual semantics of clone is to do a shallow copy (for instance, when we 'clone' a nested array). If we want to have a deep copy, the usual approach is Marshal.load(Marshal.dump(object)). Now the odd thing is that we can not "shallowly copy" nil, i.e. nil.clone is forbidden, but we can do a deep copy, i.e. Marshal.load(Marshal.dump(nil)) works. So, an alternative would be to have nil.clone simply return the identical object.

Both (1) seems to me a sound solution. The solution (2) has the drawback that we can't guarantee anymore that x.clone has a different object id than x, but is probably the behaviour a programmer would intuitively expect. 



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>