Common Lisp和Scheme词法闭包之间的差异

Pau*_*omé 3 lisp scheme lexical-closures common-lisp let

在Common Lisp中,我可以评估以下代码片段(在SBCL中),而不会发出任何语法错误信号:

(let ((x 0))
   (defun my-incf (y)
     (setf x (+ x y)))
   (defun my-decf (y)
     (setf x (- x y))))
MY-DECF

CL-USER> (my-incf 1)
1
CL-USER> (my-incf 1)
2
CL-USER> (my-decf 1)
1
CL-USER> (my-decf 1)
0
Run Code Online (Sandbox Code Playgroud)

当我尝试评估相应的Scheme代码片段时(在DrRacket中):

(let ((x 0))
  (define (my-incf y)
    (set! x (+ x y)))
  (define (my-decf y)
    (set! x (- x y))))
Run Code Online (Sandbox Code Playgroud)

它表示语法错误.

begin (possibly implicit): no expression after a sequence of internal definitions in: (begin (define (my-incf y) (set! x (+ x y))) (define (my-decf y) (set! x (- x y))))
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么不能在Scheme中做到这一点?

Chr*_*ung 10

您无法在Scheme中定义顶级以外的顶级绑定.(并且在a里面let肯定是在顶级之外 - 你所拥有的是内部定义,而不是导出到顶级.)然而,使用define-values,你仍然可以做你需要做的事情:

(define-values (my-incf my-decf)
  (let ((x 0))
    (values (lambda (y)
              (set! x (+ x y))
              x)
            (lambda (y)
              (set! x (- x y))
              x))))
Run Code Online (Sandbox Code Playgroud)

但是,您仍然可以使用内部定义,以使代码更具可读性:

(define-values (my-incf my-decf)
  (let ((x 0))
    (define (my-incf y)
      (set! x (+ x y))
      x)
    (define (my-decf y)
      (set! x (- x y))
      x)
    (values my-incf my-decf)))
Run Code Online (Sandbox Code Playgroud)

两全其美.:-)在这种情况下,values将内部my-incfmy-decf定义发送到外部define-values,这是真正的顶级定义发生的地方.