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

时间:2013-06-26 23:41:22

标签: lisp scheme common-lisp let lexical-closures

在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

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

(let ((x 0))
  (define (my-incf y)
    (set! x (+ x y)))
  (define (my-decf y)
    (set! x (- x y))))

它表示语法错误。

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))))

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

3 个答案:

答案 0 :(得分:10)

您无法在Scheme中定义顶级以外的顶级绑定。 (并且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))))

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

(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)))

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

答案 1 :(得分:3)

克里斯的解决方案就是我在这种情况下会使用的解决方案,但是这是另一个本着“让兰都达”的精神,如果你增加x上的操作次数就可以派上用场:

(define inc-dec
  (let ((x 0))
    (lambda (msg y)
      (case msg
        ((incf) (set! x (+ x y)))
        ((decf) (set! x (- x y)))
        (else (error "wot?")))
      x)))


(inc-dec 'incf 1)
(inc-dec 'incf 1)
(inc-dec 'decf 1)
(inc-dec 'decf 1)

答案 2 :(得分:0)

不太优雅,但非常简单:根据它是Scheme还是CL,定义顶级变量,然后set!setf将它们定义为let内的lambdas。