【发布时间】:2011-03-20 16:50:19
【问题描述】:
在 Common Lisp 中为值和函数设置单独的命名空间的设计决策背后的基本原理是什么?支持和反对的论据是什么?
【问题讨论】:
标签: namespaces lisp scheme common-lisp
在 Common Lisp 中为值和函数设置单独的命名空间的设计决策背后的基本原理是什么?支持和反对的论据是什么?
【问题讨论】:
标签: namespaces lisp scheme common-lisp
除了上面提到的其他问题之外,为函数提供单独的命名空间使得 CL 不卫生的宏不太可能咬住宏用户。在 CL 中,出现在宏扩展中的调用点处绑定的名称将具有在调用点使用的定义,而不是在定义宏时使用的定义。因此,在 Lisp-1 版本的 CL 中,如果宏扩展为对 LIST 函数的调用,并且 LIST 在调用宏时被定义为变量,则宏会发生故障。 (请注意,gensyms 不能解决这个问题,不像他们解决的逆问题。)
这在Scheme中不会发生,因为默认情况下Scheme宏是卫生的:宏扩展中使用的所有名称都具有它们在定义宏时的含义,而不是使用它的位置。
【讨论】:
Common Lisp 基本上是原始 Lisp 1.5 的后代,或者更确切地说,是其不同方言的统一。最初的 Lisp 1.5 就是现在所说的 Lisp-2。因为那是在 60 年代,你可以将函数传递给其他函数的事实已经够奇怪了。甚至没有人会想到让它们共享同一个命名空间。今天发明的几乎所有支持高阶函数和匿名函数的语言都选择单一命名空间方法。包括 Clojure,它在其他方面更接近于 Common Lisp 而不是 Scheme。
Scheme 和 Clojure 一样,最初并不是与 Lisp 1.5 不同的方言,对于它们的目的来说它是有意义的。
当然,在 Clojure 中,向量、散列映射、集合和所有东西也可以应用于参数,所以从某种意义上说,Clojure 中的向量可以看作是一个函数,它接受一个自然数并从中产生一个值.
【讨论】:
lambda 开头的列表。)
虽然理论上每种方式都可能有很多论据,但我敢打赌,这在很大程度上是哲学的起源。 Scheme 是一个 Lisp-1,它更喜欢优雅而不是实用性,并且为变量和函数选择了相同的 define 语法,这使得单个命名空间感觉自然(并鼓励函数式编程风格)。 Common Lisp 倾向于实用性和强大而不是优雅,并且是一种建立共识的尝试,因此看到现有的两个命名空间解决方案被广泛接受并且运行良好,就接受了它。
然而,在实践中,它主要意味着三件事:
funcall
lst 而不是 list
然而,这是为什么有些人更喜欢一种 Lisp 而不是另一种的主要因素。
【讨论】:
funcall 或避免名称冲突更深:在Scheme 中使用高阶函数更自然,因此更惯用,因此编译器会努力优化它。但是,在 CL 中,如果您使用 defvar 定义变量,然后使用 funcall 定义变量,那么编译器很可能会将其编译为比使用函数定义慢得多的代码。这类似于 CLers 更喜欢循环构造,而方案者更喜欢尾调用。但是当然你的第三点是最重要的...
我实际上喜欢拥有多个命名空间(甚至超过两个);它使用户和编译器编写者(实现)更容易:
CL-USER> (defclass test () ())
#<STANDARD-CLASS TEST>
CL-USER> (defun test ())
TEST
CL-USER> (defparameter test 42)
TEST
CL-USER> (describe 'test)
COMMON-LISP-USER::TEST
[symbol]
TEST names a special variable:
Value: 42
TEST names a compiled function:
Lambda-list: ()
Derived type: (FUNCTION NIL (VALUES NULL &OPTIONAL))
Source form:
(LAMBDA ()
(DECLARE (MUFFLE-CONDITIONS COMPILER-NOTE))
(PROGN
(SB-INT:NAMED-LAMBDA TEST
NIL
(BLOCK TEST))))
TEST names the standard-class #<STANDARD-CLASS TEST>:
Direct superclasses: STANDARD-OBJECT
No subclasses.
Not yet finalized.
No direct slots.
; No value
CL-USER> (make-instance 'test)
#<TEST {1005B1D601}>
CL-USER> (test)
NIL
CL-USER> test
42
CL-USER>
【讨论】:
(defun foo (list) (list (bar list))) 之类的东西,这不适用于单个命名空间。必须在 Scheme 中为我的论点命名,例如 lyst 或 lst,这让我有点抓狂。
list 也会让我有点发疯,因为它是如此非描述性的。我称它为source 或target 或haystack 或words,这说明了列表的目的是什么。如果我按类型调用参数,我 90% 的参数将是 list。 :-)
list-as-parameter”参数最终让我相信 Lisp-2 是不必要的,因为完全不合逻辑的原因:这种情况完全难以置信 i> (当人们重复使用同一个令人难以置信的例子时,会让人觉得立场很弱)。
请参阅 Richard P. Gabriel 的论文 Technical Issues of Separation in Function Cells and Value Cells,了解有关该主题的完整学术处理。
【讨论】: