From a language design perspective, why aren't ruby blocks first-class?
Mostly for performance reasons, in as far as I'm aware. Consider:
def test_yield
yield
end
def test_block &block
block.call
end
la = lambda {}
def test_lambda l
l.call
end
Then, benchmark with an empty block for the first two, vs the third with a new la
per call or with the same la
, and note how much faster the yield goes in each case. The reason is, the explicit &block variable creates a Proc object, as does lambda, while merely yielding doesn't.
A side-effect (which I've actually found uses for, to recursively pipe passed blocks through the use of a proc object), is you cannot yield in a proc or lambda outside some kind of enclosing scope:
foo = proc { yield if block_given? }
foo.call { puts 'not shown' }
def bar
baz = proc { yield if block_given? }
baz.call
end
bar { puts 'should show' }
This is because, as I've come to understand it (I lost a lot of hair due to this, until it ticked), block_given? is sent to main when foo calls it, and to bar rather that baz when it gets evaluated in bar.
Proc
was namedBlock
instead? – Seagrave