温馨提示:本文翻译自stackoverflow.com,查看原文请点击:lisp - Is there a function in Racket that returns a procedure's lambda-expression?
common-lisp lambda racket lisp

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

发布于 2020-04-10 10:30:06

在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中寻找这样的功能。我浏览了球拍文档,但找不到类似的东西。(但是,如果我忽略了它,我不会感到惊讶。)球拍中是否有类似的东西?

查看更多

提问者
Ashton Wiersdorf
被浏览
65
Ryan Culpepper 2020-02-01 19:14

否。Racket lambda产生的闭包不记得其S表达式(或语法对象)形式。它通常确实会记住其名称(如果无法推断出名称,则会记住其缩写位置),并且通常足以帮助进行调试。(请参阅object-name。)

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

#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)))

这产生

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

更好的版本的宏可能会将宏使用的源位置传播到lambda它创建表达式或推断的名称(请参阅参考资料syntax-local-infer-name),或两者都传播