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.