5
votes

In one variant of Common Lisp (I think it was CMUCL, but I might be wrong—I can't find it any more) there was a function that was (I think) called function-lambda-expression. If it got a procedure, it would print out the lambda expression that had generated it. Example:

(let ((my-thunk (lambda () (+ 1 2))))
    (write my-thunk)
    (write (function-lambda-expression my-thunk)))

This would print out something like:

#<PROCEDURE>
(LAMBDA () (+ 1 2))

It was terribly useful for debugging and exploring the language.

I'm looking for a function like this in Racket. I've looked through the Racket Documentation but I can't find anything like it. (I wouldn't be surprised if I overlooked it, however.) Is there an equivalent in Racket?

1
Btw., in Common Lisp both write and function-lambda-expression are standard functions.Rainer Joswig
@RainerJoswig Thanks! It's been a while, and I forgot.Ashton Wiersdorf

1 Answers

11
votes

No. Racket's lambda produces a closure that does not remember its S-expression (or syntax object) form. It does typically remember its name (or its abbreviated source location, if no name can be inferred), and that's often enough to help with debugging. (See object-name.)

You can build your own variant of lambda that has this feature, using Racket's applicable structures and a simple macro. Here's a basic example:

#lang racket

(struct exp-closure (f exp)
  #:property prop:procedure (struct-field-index f))

(define-syntax-rule (exp-lambda formals . body)
  (exp-closure (lambda formals . body)
               (quote (exp-lambda formals . body))))

(let ([my-thunk (exp-lambda () (+ 1 2))])
  (printf "fun is ~v\n" my-thunk)
  (printf "exp is ~v\n" (exp-closure-exp my-thunk))
  (printf "result is ~v\n" (my-thunk)))

This produces

fun is #<procedure:...tmp/lambda.rkt:11:19>
exp is '(exp-lambda () (+ 1 2))
result is 3

A better version of this macro might propagate the source location of the macro use to the lambda expression it creates, or the inferred name (see syntax-local-infer-name), or both.