SICP示例不适用于Racket

时间:2013-05-14 09:20:04

标签: functional-programming lisp scheme racket

我正在尝试一个关于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)(+ x x))上的definition-value应该返回一个lambda函数

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

球拍输出

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

不是“(lambda(x)(+ x x))”程序?或者它是一个参考?如果它是一个参考,任何“取消引用”它的方式?

2 个答案:

答案 0 :(得分: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-valuean interpreter的一部分。这种解释器是“解除引用”的方式,即解释函数定义。不同的解释器可以有不同的方式来解释相同的函数定义,为结果语言提供不同的语义。

表达式的评估必须在上下文中完成 - 它们出现在某些lexical scope(代码中的区域,其中变量可见)内,这会产生environments(也是,this)。在上面的示例中,y在正在解释的程序中的某个封闭范围中定义。试着通过调用Racket's eval来解释REPL中的表达式,y会有什么价值?

答案 1 :(得分:0)

我想到了答案,如果在文件中执行一个Racket脚本,racket解释器不知道命名空间,但是,REPL知道它。解决方案是在文件的开头添加此行

(define ns (make-base-namespace))

然后在使用时将ns传递给eval

(eval <what ever code reference here> ns)

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