Unbound Variables in Racket
Let's try a bit of Racket mental gymnastics. Can you create an expression that:
- doesn't use a conditional,
- contains an unbound variable, and
- whose value is not affected by the value of the unbound variable?
lambda
help?
We could try a lambda
expression:
(lambda (x) y)
y
is unbound—but if no one ever applies the
lambda
expression to an argument, then y
will never be evaluated!
But if someone does apply the lambda
to an argument,
the interpreter will evaluate the y
. So the value of
applying the lambda
depends on the value of
y
. That's another wrinkle. Can we iron it out?
Here is a hint: Suppose I have a function that makes no use of its formal parameter. That is, its value is independent of the value of any argument that is passed to it. Here is an example:
(lambda (x) (lambda (y) y))
This function takes some value, binds it to x
, and
then ignores x
, returning a lambda
expression that doesn't refer to it.
Can you use this idea to create an expression that contains a free variable and whose value doesn't depend on the value of that variable? How about this example?
( (lambda (x) (lambda (y) y)) x )
The value of this expression doesn't depend on the value of
x
! Alas, unlike the if
expression and
first lambda
expression above, the Racket interpreter
will evaluate the x
— in order to pass
it as an argument. This does, however, show us that the value of
an expression can be independent of the value of a free variable
it contains. That is a step forward.
Now we know what we have to do: write a function that:
- takes an argument containing a free variable that is never evaluated, and
- never evaluates its argument.
If we pass a lambda
expression that contains a free
variable, the variable won't be evaluated until the
lambda
is applied. But if the receiving function
never uses its argument, the free variable will never be
evaluated!
So:
> ( (lambda (x) (lambda (z) z)) (lambda (x) y) ) #<procedure>
The y
in the function passed as an argument is free,
but never evaluated. We can apply this function to any argument:
> (((lambda (x) (lambda (z) z)) (lambda (x) foo)) 'x) 'x
Yes, this is only an academic exercise. You won't ever need such a function, certainly not in this course. Dr. Racket won't even let you do it in source code! But it's a useful little puzzle to help us explore and understand better the idea of free and bound variables.
Sometimes, computer scientists like to play fun little games that other people might not see as fun! I hope you at least find it instructive.