Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a function in Racket that returns a procedure's lambda-expression?

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?

like image 224
Ashton Wiersdorf Avatar asked Feb 01 '20 07:02

Ashton Wiersdorf


People also ask

Can you return a lambda function?

The lambda function can take many arguments but can return only one expression.

What does lambda mean in Racket?

In Racket (and other functional programming languages) lambda s are very useful, when you want to pass an in-line, one-shot function as a parameter without defining it first. For example, suppose that we want to square a list of numbers.

What does apply do in Racket?

racket Functions The `apply` function The major advantage of apply is that it works on arbitrary computed lists, including appended lists and lists that come from function arguments.


1 Answers

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.

like image 158
Ryan Culpepper Avatar answered Oct 04 '22 14:10

Ryan Culpepper