A popular game on comp.lang.lisp is comparing Lisp with Python. Lispers complain that Python has a crippled lambda and no lexical closures, and they hiss and boo whenever Python’s development tends in a non-functional direction.
I’ve recently been playing with Ruby. Lo and behold, it has real lambdas, closures, and a generally more functional style. The syntax is almost as clean as Python’s, without that significant whitespace that raises so many hackles.
One thing I don’t yet understand about Ruby is the way it treats functional arguments. A function or method in Ruby can have only one functional argument, which must be the last argument. Functional arguments, or “blocks,” as they’re called in Ruby, appear outside the argument list of the function when it is called. So it looks like this for short blocks:
object.method(arg1, arg2) { |var| block code }
Or like this for multi-line blocks:
object.method(arg1, arg2) do |var| block code . . . end
In both examples, |var| is the block’s own argument list, so the Lispy equivalent of the above would be:
(method object arg1 arg2 (lambda (var) . . . ))
The main advantage to this syntax comes with iterators, which I take it were the reason Ruby got blocks in the first place. Ruby’s iterators are just methods of container objects that take a block as their only argument. Then one can omit the parentheses to get something like:
list.each do |item| do stuff with item end
This looks a bit like Smalltalk, one of Ruby’s inspirations. The Smalltalk approach has the advantage that most control constructs are just object methods, so they can be extended and modified as needed. (Unlike Smalltalk, Ruby has a few primitive controls that are not methods, such as if.)
So the special syntax for blocks isn’t strictly necessary, but it does make the most common use for blocks syntactically very simple. In short, a compromise. Ruby also provides the Proc class when general-purpose lambdas are needed.
I won’t advocate Lisp, Ruby, or Python over any other language; each has its place. But Lispers looking for a compromise with Python may want to give Ruby a spin.

Entries (RSS)