|
|
|
|
|
by judofyr
250 days ago
|
|
Blocks are fundamentally different from functions due to the control flow: `return` inside a block will return the outer method, not the block. `break` stops the whole method that was invoked. This adds some complexity in the language, but it means that it’s far more expressive. In Ruby you can with nothing but Array#each write idiomatic code which reads very similar to other traditional languages with loops and statements. |
|
This can sometimes be useful: A calling method can pass down a block or proc to control if/when it wants an early return.
Basically Ruby has two types of closures:
* A return in a lambda returns to the calling scope. So basically, it returns to after where the "call" method is invoked.
* A return in a block or a proc returns from the scope in which it was defined (this is also why you get LocalJumpError if you try to return a block or a proc, but not a lambda to the method calling the one where the block or proc is defined).
When you name a block, you get a Proc object, same as you get when you take the value of a lambda or proc.
In practice, that blocks in MRI are not Proc objects already is just an implementation detail/optimisation. I have a long-standing hobby project to write a Ruby compiler, and there a "proc" and a bare block are implemented identically in the backend.