【发布时间】:2013-06-24 07:26:51
【问题描述】:
在 Common Lisp 中,我可以评估以下 sn-p 代码(在 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 sn-p 代码时(在 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中完成吗?
【问题讨论】:
-
您需要查看 DrRacket 中 LET 的语法定义。 Common Lisp 示例是有效的,但我不会在我的代码中使用它。
-
我会改用 CLOS。使用上述方法会使调试更加困难,并且会阻止 DEFUN 形式被编译器识别为函数定义。在 LET 中,DEFUN 不再是顶级表单。
-
不是很明显吗? X 是 CLOS 实例中的一个插槽。那么函数就是方法。
-
顺便说一句,关于你正在做的事情与你可以用 CLOS 做的事情的相似性,Scheme 最初是作为一种探索面向对象思想的语言而发明的——大概使用类似于那些如下所述。
-
我不一定会使用 OOP 来解决具有全局变量的模块的简单问题。函数不是顶级表单的问题可以通过
(defvar *counter* 0)解决,函数参考*counter*。如果模块尖叫“我真的应该是一个支持多个实例化的对象,并且所有这些全局变量都应该是我的实例变量”,则适用 OOP 方法。如果您没有预料到需要多次实例化,或者没有任何继承等好处,请坚持使用全局变量。动态变量是执行全局变量的“Common Lispy”方式。
标签: lisp scheme common-lisp let lexical-closures