I found out from heckle that
[1, 2, 3].each(&nil)
doesn't cause any errors - it just returns an enumerator.
By contrast,
[1, 2, 3].each(&"")
raises
TypeError: wrong argument type String (expected Proc)
Also, &nil
causes block_given? to return false
def block_given_tester
if block_given?
puts "Block given"
else
puts "Block not given"
end
end
block_given_tester(&nil) # => Block not given
It's not because NilClass
implements to_proc
- I checked the RDoc.
I can understand why it'd be nice to have &nil
, but I'm not sure how it's done. Is this just one of the ways nil
has special behavior not shared by other objects?
The answer can be found by looking at Ruby's source code.
Ruby 1.8:
Look at the function
block_pass
in the fileeval.c
. Note that it treatsnil
specially fromProc
objects (the macroNIL_P
). If the function is passed a nil value, it evaluates an empty block (I think) and returns. The code right after it checks whether the object is aProc
object (the functionrb_obj_is_proc
) and raises the exception "wrong argument type (expected Proc)" if it isn't.Ruby 1.9.2:
Look at the method
caller_setup_args
in the filevm_insnhelper.c
. It converts the proc withto_proc
only if it is not nil; otherwise, the type conversion and type check are bypassed.