I think a clearer way to put the distinction is that in Ruby, blocks serve both as lambdas AND to let you define new control structures (that are thus analogous to for loops). Combining the two lets you do things that you can't do just with lambdas, and if you want to make an argument as to why blocks are flexible that's the right argument to make. For example, to wrap file access in the appropriate open/close functionality while still letting you return early via the block.
Unfortunately, it can also result in some serious confusion on the part of a programmer that wants to think of them as lambdas. Java was originally going to do something similar and have two types of lambdas in 1.7, one using => and the other using ==> to indicate the non-local return semantics, and I think it would have confused a ton of people.
If you have a filter that takes a predicate function, for example, you might naively do (excuse my incredibly-rusty-and-thus-totally-syntatically-mangled-Ruby):
some_list.filter() |x| do
if (x.foo)
return true
else
return false
end
In this case, you'll end up returning from the outer function, NOT just returning a true/false value for filtering. To do that, you have to just do:
some_list.filter() |x| do
if (x.foo)
true
else
false
end
And rely on the way that things you might otherwise think of as statements are expression values in Ruby. But what if my predicate function is really complicated, and I want to end the block early? Um . . . too bad. Better put that in its own function and call that function from your block.
I'm sure that in practice those aren't major issues for people used to Ruby idioms and behavior, but from someone new to Ruby they can really trip you up.
Unfortunately, it can also result in some serious confusion on the part of a programmer that wants to think of them as lambdas. Java was originally going to do something similar and have two types of lambdas in 1.7, one using => and the other using ==> to indicate the non-local return semantics, and I think it would have confused a ton of people.
If you have a filter that takes a predicate function, for example, you might naively do (excuse my incredibly-rusty-and-thus-totally-syntatically-mangled-Ruby):
some_list.filter() |x| do if (x.foo) return true else return false end
In this case, you'll end up returning from the outer function, NOT just returning a true/false value for filtering. To do that, you have to just do:
some_list.filter() |x| do if (x.foo) true else false end
And rely on the way that things you might otherwise think of as statements are expression values in Ruby. But what if my predicate function is really complicated, and I want to end the block early? Um . . . too bad. Better put that in its own function and call that function from your block.
I'm sure that in practice those aren't major issues for people used to Ruby idioms and behavior, but from someone new to Ruby they can really trip you up.