Understanding lambda substitution in Redex

114 Views Asked by At

Let us say I have the following defined in Redex:

(define-language L
    [e ::= (λ x e) (e e) x]
    [x ::= variable-not-otherwise-mentioned]
    #:binding-forms
    (λ x e #:refers-to x))

Now, I would think that the expression (λ y x) x means:

replace occurrence of y in x (inside braces in the above expression) with x (outside braces). And since there is no y in x, the answer should be just x. Then (λ y x) x y should return x y. But:

(default-language L)
(term (substitute (λ y x) x y))
'(λ y«0» y)

why does it return a function? And what does y<<0>> mean? Am I misunderstanding term (substitute ..)?

I didn't understand this result either:

(term (substitute (λ y x) x true))
'(λ y«1» true)

Could someone help me decipher this? I'm new to Racket/Redex.

1

There are 1 best solutions below

0
On BEST ANSWER

y«0» and y«1» simply mean that while the variable is named y, its a different y than the one passed in. The #:refers-to flag is used to make forms respect capture-avoiding substitution.

In general, the idea is this, what should the result of this program be:

((lambda (x) (lambda (y) x))
 y)

Should this program evaluate to 4 or 3? If we use simple substitution, then we can say that the program reduces to:

(lambda (y) y)

Which is the identity function. This is noticeable if we, say, bound y to 5 and called the result:

(let* ([y 5]
       [f ((lambda (x) (lambda (y) x))
            y)])
  (f 6))

Here, we would expect the result to be 5, even though we are passing 6 into f. This is because the y in the result is pointing to the first y in the let*. You can see this if you mouse of y in DrRacket.

To avoid this, rather than doing a simple substitution of all xs in the expression to ys, it renames all binders going down to new names, so instead you get:

(lambda (y«0») y)

And now its clear that the two ys in this expression are different.