21212
21212

Reputation: 39

Lambda inside function definition Scheme

(define (fn lst)
  (filter (lambda (item) (not (symbol=? item 'sym))) lst))

We pass in lst, but inside (lambda (item) (not (symbol=? item 'sym))) our variable lst is never used. Evaluation?

Upvotes: 0

Views: 1260

Answers (1)

Alexis King
Alexis King

Reputation: 43902

The code snippet you posted combines two concepts which can be explained in isolation (and might make more sense that way): lambda expressions and higher-order functions.

Lambda expressions

In Scheme/Racket, functions are ordinary values, just like numbers or lists. To create a number, you just type it, like 3 or 25. To create a list, you use the list function, like (list 2 4 6). To create a function, you use the lambda form.

Normally, when you define a function, you use define. For example, here is a function that adds 1 to a number:

(define (add1 x)
  (+ x 1))

But this is really just a shorthand syntax. The full way of writing the above definition out would look like this:

(define add1
  (lambda (x)
    (+ x 1)))

As you can see, it uses lambda.

Why would using lambda directly ever be useful, though, if the define shorthand is shorter and easier to read? Well, to understand that, you must consider higher-order functions.

Higher-order functions

Most functions take simple values and produce simple values. For example, the add1 function above takes a number as an argument and produces a number as a result. However, remember above that I mentioned that functions are values, too. For that reason, functions can actually accept other functions as arguments, and they can even produce other functions as results. These functions are called “higher-order functions”.

The filter function is a higher-order function. It takes a function and a list, and it uses the function to select which elements should be kept in the result. For example, it can be used to select all the even numbers in a list:

> (filter even? (list 1 2 3 4 5))
'(2 4)

Note that even? is a function, and it’s being passed as an argument to filter. This is totally okay, and it’s actually extremely useful! There are many functions in Scheme/Racket that are higher-order, and these sorts of functions are an important part of programming in a “functional” style. For example, the map function lets you provide a function to apply to each element of a list:

> (map add1 (list 1 2 3 4 5))
'(2 3 4 5 6)

This is all well and good, of course, but what if you wanted to add a number other than 1 to each element of a list? Well, you could always define a new function that added the right amount:

> (define (add25 x)
    (+ x 25))
> (map add25 (list 1 2 3 4 5))
'(26 27 28 29 30)

However, this would be extremely silly. It would be like if you had to give names using define to all of your numbers, too, instead of just typing them into the program directly. For small, simple functions that will only be used once, giving them a name is unnecessary. For that, you can use the lambda form directly:

> (map (lambda (x) (+ x 25))
       (list 1 2 3 4 5))
'(26 27 28 29 30)

This is what is happening in the snippet in your question. You could give the inner lambda a name, like this:

(define (not-an-apple? item)
  (not (symbol=? item 'apple)))

(define (eat-apples lst)
  (filter not-an-apple? lst))

However, in this case it’s easier to just write the function inline, since having a separate not-an-apple? function is probably not terribly useful.

Upvotes: 4

Related Questions