In Racket (and other functional programming languages) lambda
s are very useful, when you want to pass an in-line, one-shot function as a parameter without defining it first. For example, suppose that we want to square a list of numbers. We can go the long way and define a square
function first, and then use map
:
(define (square x)
(* x x))
(map square '(1 2 3 4 5))
=> '(1 4 9 16 25)
… Or we can simply pass a lambda
, like this:
(map (lambda (x) (* x x))
'(1 2 3 4 5))
=> '(1 4 9 16 25)
As you can see, there exist cases where we don't need to refer to a function's name. Of course, if the procedure represented by the lambda
is going to be reused in several parts, or if it's recursive then it makes sense to give it a name (so it's no longer anonymous):
(define square
(lambda (x) (* x x)))
The above is equivalent to the first definition of square
at the beginning. In fact, the first definition is just syntactic sugar to define a function, but in the end all functions are lambdas!
Now let's see your example. Here we are using a lambda
in a slightly different fashion, and also exemplifies why they're useful - we're not only defining a function, but returning a function as well:
(define test
(lambda (x)
(lambda (y)
(+ x y))))
Perhaps it'll be a bit clearer if we write it like this (it's equivalent, for the reasons mentioned above):
(define (test x)
(lambda (y)
(+ x y)))
Or even shorter - in Racket we can also use this syntax for the same purpose:
(define ((test x) y)
(+ x y))
It's not that this is a better (or worse) way to define a function - it's a different thing! we're defining a procedure called test
, that receives as parameter x
and returns as a result a new anonymous function, that in turn will receive as parameter y
. Now, in these lines:
(define add27
(test 27))
… we're calling test
with an x
value of 27
, which returns the anonymous function, and we name that function add27
. Remember the lambda
that received as parameter y
? now that lambda
has been named add27
- and this is an example of currying. Think of it: test
is a function that is used for generating functions that add a fixed value x
to a given parameter y
, that explains why this works:
(add27 2)
=> 29
On the other hand, this function will always add 27
to its parameter with no way to change it:
(define (addTest x)
(+ x 27))
(addTest 2)
=> 29
You see the difference? test
allows us to generate new functions that add an arbitrary value, whereas addTest
always adds a fixed value, 27
. What if you wanted to add say, 100
? using test
this is simple:
(define add100 (test 100))
But addTest
can't be changed, we would need to write a new function:
(define (addTest100 x)
(+ x 100))
I hope this clarifies things, feel free to ask in the comments any additional questions about my answer.