1

我正在尝试 SICP 第 4 章的示例(编写 LISP 解释器的一部分)

(define (definition-value exp)
    (if (symbol? (cadr exp))
        (caddr exp)
        (make-lambda 
                    (cdadr exp) ; formal parameters
                    (cddr exp)  ; body
        )              
    )
) 


(define (make-lambda parameters body)
    (cons 'lambda (cons parameters body))
)

我测试过,'(define (double x) (+ xx))) 上的定义值应该返回一个 lambda 函数

( (definition-value '(define (double x) (+ x x))) 10)

球拍输出

procedure application: expected procedure, given: (lambda (x) (+ x x)); arguments were: 10

“(lambda(x)(+ xx))”不是一个过程吗?或者它是一个参考?如果是引用,有什么方法可以“取消引用”它?

4

2 回答 2

2

definition-value返回作为参数提供给它的定义表达式中的值:

(definition-value '(define x 42))  
=> 42

(definition-value '(define (qq x) (+ x y 42))) 
=> (make-lambda '(x) '((+ x y 42)))
=> '(lambda (x) (+ x y 42))

您不能像您一样将引用的列表称为函数:( '(lambda (x) (+ x y 42)) 10)无效。它不是一个函数,它只是一个s-expression

definition-value解释器的一部分。这个解释器是“取消引用”的方式,即解释函数定义。不同的解释器可以有不同的方式来解释相同的函数定义,从而为生成的语言提供不同的语义。

表达式的评估必须在上下文中进行 - 它们出现在特定的词法范围内(代码中变量可见的区域),这会产生环境(也就是 this)。在上面的例子中,y被定义在被解释程序的某个封闭范围内。试图通过调用Racket'seval来解释 REPL 中的表达式,会有什么值y

于 2013-05-14T09:30:10.910 回答
0

我想出了答案,如果在文件中执行球拍脚本,球拍解释器不知道名称空间,但是,REPL 知道它。解决方法是在文件开头添加这一行

(define ns (make-base-namespace))

然后在使用时将ns传给eval

(eval <what ever code reference here> ns)

这将使我上面提到的例子起作用。

于 2013-05-15T17:55:11.517 回答