Let's start off by saying I'm not anti-Ruby. I like Ruby. Ruby is cool. Matz is cool. But, a while back I was wondering, What is a Ruby code block? My feeble curiosity has been revealed for the half-assed dilettantery it is by Paul Cantrell. Mr. Cantrell chases this question down, grabs it by the scruff of the neck, and wrings it out like a bulldog with a new toy. He also rocks on the piano, by the way.
So in fact, there are no less than seven -- count 'em, SEVEN -- different closure-like constructs in Ruby:
- block (implicitly passed, called with yield)
- block (&b => f(&b) => yield)
- block (&b => b.call)
- Proc.new
- proc
- lambda
- method
This is quite a dizzing array of syntactic options, with subtle semantics differences that are not at all obvious, and riddled with minor special cases. It's like a big bear trap from programmers who expect the language to just work. Why are things this way? Because Ruby is:
- designed by implementation, and
- defined by implementation.
Again, neither I nor Mr. P.C. are bashing Ruby. He shows how to pull off some tasty functional goodness like transparent lazy lists later in the article. Thanks to railspikes for the link.
That doesn't look like seven different closure constructs to me. It looks like three different ways to pass and/or call a block, two different ways to create a Proc, then lambda and Method - four different constructs. I didn't know the differences between any them until I read this article, but now it seems fairly clear.
ReplyDeleteDiscussed on hacker news:
ReplyDeletehttp://news.ycombinator.com/item?id=1241780