Racket 中是否有返回过程的 lambda 表达式的函数?



在Common Lisp的一个变体中(我认为它是CMUCL,但我可能是错的 - 我再也找不到它了(有一个函数(我认为(叫做function-lambda-expression。如果它有一个过程,它将打印出生成它的 lambda 表达式。例:

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

这将打印出类似以下内容:

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

它对于调试和探索语言非常有用。

我正在 Racket 中寻找这样的功能。我已经浏览了球拍文档,但我找不到类似的东西。(但是,如果我忽略了它,我不会感到惊讶。球拍中有等价物吗?

No.Racket 的lambda产生一个不记得其 S 表达式(或语法对象(形式的闭包。它通常会记住它的名称(或缩写的源位置,如果无法推断出名称(,这通常足以帮助调试。(请参阅object-name

您可以使用 Racket 的适用结构和简单的宏构建自己的具有此功能的lambda变体。下面是一个基本示例:

#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 ~vn" my-thunk)
(printf "exp is ~vn" (exp-closure-exp my-thunk))
(printf "result is ~vn" (my-thunk)))

这会产生

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

此宏的更好版本可能会将宏使用的源位置传播到它创建lambda表达式或推断的名称(请参阅syntax-local-infer-name(,或两者兼而有之。

最新更新