It's true, you don't need anonymous functions (or lambdas, or whatever you want to call them). But there are a lot of things you don't need. You don't need classes—just pass all the instance variables around to ordinary functions. Then
class Foo
attr_accessor :bar, :baz
def frob(x)
bar = baz*x
end
end
would become
def new_Foo(bar,baz)
[bar,baz]
end
def bar(foo)
foo[0]
end
# Other attribute accessors stripped for brevity's sake
def frob(foo,x)
foo[0] = foo[1]*x
end
Similarly, you don't need any loops except for loop...end
with if
and break
. I could go on and on.1 But you want to program with classes in Ruby. You want to be able to use while
loops, or maybe even array.each { |x| ... }
, and you want to be able to use unless
instead of if not
.
Just like these features, anonymous functions are there to help you express things elegantly, concisely, and sensibly. Being able to write some_function(lambda { |x,y| x + f(y) })
is much nicer than having to write
def temp(x,y)
x + f(y)
end
some_function temp
It's much bulkier to have to break off the flow of code to write out a def
fed function, which then has to be given a useless name, when it's just as clear to write the operation in-line. It's true that there's nowhere you must use a lambda, but there are lots of places I'd much rather use a lambda.
Ruby solves a lot of the lambda-using cases with blocks: all the functions like each
, map
, and open
which can take a block as an argument are basically taking a special-cased anonymous function. array.map { |x| f(x) + g(x) }
is the same as array.map(&lambda { |x| f(x) + g(x) })
(where the &
just makes the lambda "special" in the same way that the bare block is). Again, you could write out a separate def
fed function every time—but why would you want to?
Languages other than Ruby which support that style of programming don't have blocks, but often support a lighter-weight lambda syntax, such as Haskell's \x -> f x + g x
, or C#'s x => f(x) + g(x);
2. Any time I have a function which needs to take some abstract behavior, such as map
, or each
, or on_clicked
, I'm going to be thankful for the ability to pass in a lambda instead of a named function, because it's just that much easier. Eventually, you stop thinking of them as somehow special—they're about as exciting as literal syntax for arrays instead of empty().append(1).append(2).append(3)
. Just another useful part of the language.
1: In the degenerate case, you really only need eight instructions: +-<>[].,
. <>
move an imaginary "pointer" along an array; +-
increment and decrement the integer in the current cell; []
perform a loop-while-non-zero; and .,
do input and output. In fact, you really only need just one instruction, such as subleq a b c
(subtract a
from b
and jump to c
if the result is less than or equal to zero).
2: I've never actually used C#, so if that syntax is wrong, feel free to correct it.