你为什么要重新定义`lambda`?

时间:2017-08-06 03:06:37

标签: scheme semantics language-design chez-scheme

我不明白这两个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,但我认为在实际运行该代码之前,这会因语法错误而失败。在我看来,要知道这是语法错误,你需要实际运行程序,但如果这是行为,那么我希望第一个程序在错误之前显示字符串出。

简而言之,为什么第一个程序导致语法错误而第二个程序没有?

2 个答案:

答案 0 :(得分:0)

正如Alexis所说,重新定义lambda是完全可以的。

在您的第一个示例中,您正在对参数definea(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!