You can't believe everything you read on the internet. For example, you'll read that, in Ruby, use of the return keyword is optional. Like this:
def foo(a) return a*a end foo(9) >>81 def bar(a) a*a end bar(8) >>64
So far, so good. You'll also read that a code block in Ruby is an anonymous function. And what could be more natural than to return from a function? But try this:
[1,2,3].map {|a| a*a} >> [1,4,9] [4,5,6].map {|a| return a*a} >> LocalJumpError: unexpected return >> from (irb):14 >> from (irb):14:in `map' >> from (irb):14 >> from :0
Well then, apparently one or both of our premises is wrong. Anyway, what is this LocalJump thing that is apparently in error?
My guess as to what's really going on is this: The code block is an attempt at creating a function-like artifact that matches the behavior of a code block in a non-functional language. That is, the code in the block doesn't execute in its own environment. Calling a code block doesn't cause a stack frame to be created. The reason the return causes problems is that there's no separate environment to return from.
It bothers me that I can't seem to google up an explanation of exactly what a Ruby code block (or Proc or lambda or method for that matter) is in terms of what does or doesn't happen to stack frames or environments. There's plenty of tutorials on how to use these constructs, but, little information on what they are, how they work, or why there are so many flavors of function-like things in Ruby.
Here's what I got from comp.lang.ruby.
Some clues are to be had here:
ReplyDeletehttp://railspikes.com/2008/9/8/lambda-in-ruby-1-9
See follow-up here: Principle of least surprise my ass
ReplyDeleteGood timing, I just saw this yesterday:
ReplyDeletehttp://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/
Matz on Blocks and Closures
ReplyDelete