> have fun working out the semantics of break and next when used in a block that isn't an argument to an enumeration method.
The semantics are:
* next returns from the block, optionally taking a return value that will be returned as the result of the function (this is identical to the behavior of "return" from a Proc with lambda semantics)
* break returns from the function that yielded to the block, optionally taking a return value that will be returned as the result of the function (EDIT: deleted comparison to returns from a Proc with proc rather than lambda semantics here, because it wasn't quite accurate.)
This is, incidentally, also exactly the semantics when they are called from a block passed to an enumeration method, there is no special case there.
> How do you as a method author opt in to distinguishing between the two after yielding to a block?
If control returns to your method, it was a return from the block, either via return (from a block with lambda semantics), next, or running through the end of the block. If, OTOH, break is called (or return from a block with proc semantics), control won't return to the calling method normally, but code in any "ensure" sections applicable will be run, which can be used to identify that this has occurred, and even to override the return value provided by the break.
The simplest possible function illustrating this:
def how_exited
yield
direct = true
return "next, completion, or lambda return"
rescue
direct = true
return "exception"
ensure
return "break" if not direct
end
The semantics are:
* next returns from the block, optionally taking a return value that will be returned as the result of the function (this is identical to the behavior of "return" from a Proc with lambda semantics)
* break returns from the function that yielded to the block, optionally taking a return value that will be returned as the result of the function (EDIT: deleted comparison to returns from a Proc with proc rather than lambda semantics here, because it wasn't quite accurate.)
This is, incidentally, also exactly the semantics when they are called from a block passed to an enumeration method, there is no special case there.
> How do you as a method author opt in to distinguishing between the two after yielding to a block?
If control returns to your method, it was a return from the block, either via return (from a block with lambda semantics), next, or running through the end of the block. If, OTOH, break is called (or return from a block with proc semantics), control won't return to the calling method normally, but code in any "ensure" sections applicable will be run, which can be used to identify that this has occurred, and even to override the return value provided by the break.
The simplest possible function illustrating this: