1
votes

There is a make-posn built into racket by default. Here is an implementation with lambda.

(define (my-make-posn x y)
  (lambda (s)
    (cond [(symbol=? s 'x) x]
          [(symbol=? s 'y) y]))

But this returns (lambda (a1) ...) when I attempt (my-make-posn 3 2).

Why is it like this?

I don't see how lambda is used here?

We type in (my-make-posn 3 2) and the function body is:

(lambda (s)
  (cond [(symbol=? s 'x) x]
        [(symbol=? s 'y) y]))

So what happens to the (3, 2)?

2
Please don't mangle your question - if you want to add more content or additional questions, go on. If you want to inquire on an answer, do so in the comments. - Michael Foukarakis

2 Answers

0
votes

You're calling my-make-posn wrong; you should be accessing the bound variables by symbol instead:

> ((my-make-posn 3 2) 'x)
3
> ((my-make-posn 3 2) 'y)
2

The lambda is being used to conditionally return x or y.

0
votes

This sort of “encoding” of a posn leverages the fact that lambdas are lexical closures. This means that lambdas have access to values that are in scope where they are defined, even if they are local bindings. For example, consider this simpler use of a function that returns a lambda:

(define (make-adder x)
  (lambda (y) (+ x y)))

This is a function that returns a function. The resulting function takes one argument. You can see how it’s used like this:

> (define add1 (make-adder 1))
> (add1 1)
2
> (add1 2)
3
> (define add2 (make-adder 2))
> (add2 1)
3
> (add2 2)
4

Since functions are just ordinary values, you can also use the resulting function directly, without binding it to a variable name:

> ((make-adder 10) 5)
15

How does this work? Well, consider the definition of make-adder. The inner lambda uses x, which is an argument to the make-adder function. Since lambdas are closures, this is totally fine, and x effectively becomes “locked” to the value provided to make-adder; that is, x is “closed over” by the inner lambda, hence the name.

For a more concrete example of this, you can imagine evaluating make-adder as a sort of substitution:

1. (make-adder 1)   ; given

2. ((lambda (x)     ; substitution of the
      (lambda (y)   ; definition of make-adder
        (+ x y)))
    1)

3. (lambda (y)      ; lambda reduction, substituting
     (+ 1 y))       ; 1 for x within the body

The same thing is being used for my-make-posn. We can do the same sort of expansion for (my-make-posn 3 2):

1. (my-make-posn 3 2)                  ; given

2. ((lambda (x y)                      ; substitution of the
      (lambda (s)                      ; definition of my-make-posn
        (cond [(symbol=? s 'x) x]
              [(symbol=? s 'y) y])))
    3 2)

3. (lambda (s)                         ; lambda reduction, substituting
     (cond [(symbol=? s 'x) 3]         ; 3 for x and 2 for y within the body
           [(symbol=? s 'y) 2]))

Therefore, the result is a function that takes a symbol, either 'x or 'y, and produces one of the two arguments provided to the original my-make-posn function.