My understanding is that a block implicitly attached to a method must be yielded; it cannot be called. So I'm trying to understand why this works:
def execute_code
proc.call
end
execute_code { "Why does this work?" } # => "Why does this work?"
Attaching a block to this code executes successfully.
Any insight? I haven't found any documentation hinting that an implicit block is automatically converted to a proc object and assigned to the variable proc
.
Ruby 2.5.3
For Ruby 2.5.3, the docs for Kernel#proc()
say:
Equivalent to Proc.new.
and the docs for Proc.new
say:
Creates a new
Proc
object, bound to the current context.Proc::new
may be called without a block only within a method with an attached block, in which case that block is converted to theProc
object.
which is what is happening in your example. You are calling proc
in a method with a block, and the block is being converted to a Proc.
However this behaviour changes in later versions. If you try in Ruby 2.7,1 you will get a warning like this (although it will still work):
proc.rb:2: warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead
In Ruby 3, it won’t work at all (and in fact behaves as you seem to expect):
proc.rb:2:in `proc': tried to create Proc object without a block (ArgumentError)
from proc.rb:2:in `execute_code'
from proc.rb:5:in `<main>'
The docs for 3.0.0 are unchanged though. This looks like a bug in the docs (it has been fixed in master). It looks like this was first raised in the issue tracker in 2014 and then later in 2019.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With