我不明白这两个Scheme程序之间的以下行为:
计划1 :
(define a
(begin
(display "hmmm")
(newline)
lambda))
此程序使用scheme test.ss
运行,在lambda
行显示语法错误,而不打印字符串"hmm"
。
计划2 :
(define lambda 5)
(define a (+ 1 2 lambda))
此处的最终结果是a
等于8
。
第一个程序中的行为是我在两个程序中所期望的行为。令我困惑的是为什么第二个程序没有因语法错误而失败。显然我正在重新定义lambda
,但我认为在实际运行该代码之前,这会因语法错误而失败。在我看来,要知道这是不语法错误,你需要实际运行程序,但如果这是行为,那么我希望第一个程序在错误之前显示字符串出。
简而言之,为什么第一个程序导致语法错误而第二个程序没有?
答案 0 :(得分:0)
正如Alexis所说,重新定义lambda是完全可以的。
在您的第一个示例中,您正在对参数define
,a
,(display "hmmm")
和(newline)
调用过程lambda
。由于Scheme是一种急切的语言,它试图在执行之前评估每个参数,这很可能是在评估lambda时失败的原因(因为在这种情况下,lambda是一个期望一些参数id的过程:{ {3}})。
第二个示例成功,因为在参数define
上调用a
和求和(+ 1 2 lambda)
时,求和解析为有形类型(因为lambda已重新定义为整数)。
希望有所帮助。
答案 1 :(得分:0)
在Scheme lambda
中,define
是编译器阶段的顶级绑定。 define
只需要两个操作数,因为你提供了4个操作数,它应该首先对它做出反应。所以首先修补一下:
(define a
(begin
(display "hmmm")
(newline)
lambda)))
现在您收到有关lambda
的错误消息。这是创建过程的原始形式,因此编译器认为您使用错误:
(lambda (x) (+ x x)) ; implementation of double
如果您已将lambda
定义为变量,那么错误将不会发生,因为即使这是制作过程的方法,您也可以使用相同的名称创建变量。
(define lambda 10)
(define a
(begin (display "hmmm")
(newline)
lambda))
; ==> 10 (and it printed "hmmm")
编译器知道代码的词法性质。它确切地知道哪些绑定被定义,哪些是水平和哪个阶段。顶级lambda
已不再可用。
现在在你的第二个程序中你定义lambda
然后使用它,就像我最后一个也可以使用的例子一样。
请注意,在R5RS中,编译器假定重新定义og库和原始过程是兼容的并且可能是常量折叠:
(define (+ a b)
(string-append a b))
(display (+ 4 5)) ; displays 9
在我的辩护中,我通过使+
不兼容而侵犯了R5RS报告。如果它不是最高级别就可以了:
(let ((+ (lambda (a b) (string-append a b))))
(+ 4 5)) ; no loinger top level, will signal n error!