1

假设我在某处定义了几个符号:

#lang racket
(define foo 123)
(define bar '("1" "2" "3"))

我需要一种方法来生成类似"foo = 123"or的字符串"bar = '("1" "2" "3")"。我为此写了一个函数:

(define (f2 sy)
  (format "~a = ~s" sy (eval sy)))

此功能在解释器窗口中运行良好。

> (f2 'foo)
"foo = 123"
> (f2 'bar)
"bar = (\"1\" \"2\" \"3\")"

这对我来说是相当满意的。但是,当我在代码中使用它时,我得到

foo: unbound identifier;
 also, no #%top syntax transformer is bound in: foo

我有一种感觉,我做错了什么。您能否提出解决我问题的正确方法?

PS:我正在使用DrRacket, version 5.3.1

4

2 回答 2

1

首先,eval真的应该只在 Racket 中作为最后的手段使用。它使您的程序效率降低且更难理解。这样做的正确方法可能是编写如下宏:

(define-syntax-rule (f2 sy)
  (format "~a = ~s" (quote sy) sy))

(define foo 2)
(f2 foo)

该宏只是将您要查找的变量的名称替换为正文中的格式表达式。将quote变量名称转换为可以打印的符号。这个宏不能作为一个过程工作,因为在你可以之前(f2 foo)会尊重并打印它的名字。fooquote


eval注意:您无法按预期工作的原因是因为eval总是针对命名空间进行评估,这决定了范围内的内容。模块中的默认命名空间中没有任何内容,因此eval看不到foo或其他任何内容。您可以在指南中阅读有关命名空间的更多信息。

于 2013-03-10T15:57:53.097 回答
1

另一种解决方案,也受到 Asumu Takikawa 的启发,使用了指南中描述的技巧:

(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))

(define (f2 sy)
  (format "~a = ~s" sy (eval sy ns)))

与使用宏的解决方案相比,可以映射此功能。

于 2013-03-10T20:20:01.180 回答