Scheme 为所有变量使用一个命名空间,无论它们是绑定到函数还是其他类型的值。Common Lisp 将两者分开,因此标识符“hello”在一个上下文中可能指代一个函数,而在另一个上下文中指代一个字符串。
(注1:这个问题需要上面的一个例子;随意编辑它并添加一个,或者用它给原作者发电子邮件,我会这样做。)
但是,在某些情况下,例如将函数作为参数传递给其他函数,程序员必须通过使用明确区分他指定的是函数变量,而不是非函数变量,#'
如下所示:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
我一直认为这有点像疣,但我最近遇到了一个论点,认为这实际上是一个特性:
...重要的区别实际上在于形式的语法,而不是对象的类型。在不知道所涉及的运行时值的情况下,很明显函数形式的第一个元素必须是函数。CL 接受了这一事实并将其与宏和特殊形式一起成为语言的一部分,这些形式也可以(并且必须)静态确定。所以我的问题是:当函数名的主要用途是出现在变量名很少出现的地方时,为什么你希望函数名和变量名在同一个命名空间中?
考虑类名的情况:为什么一个名为 FOO 的类要阻止使用名为 FOO 的变量?我唯一一次用 FOO 来引用这个类是在需要类名的上下文中。如果在极少数情况下我需要获取绑定到类名 FOO 的类对象,则可以使用 FIND-CLASS。
从经验来看,这个论点对我来说确实有意义。Haskell 中也有类似的情况,字段名称也是用于访问字段的函数。这有点尴尬:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
这可以通过一些额外的语法来解决,NamedFieldPuns
扩展特别好:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
那么,对于这个问题,除了一致性之外,Common Lisp 与 Scheme 以及一般而言,所有值的单个命名空间与函数和非函数值的单独命名空间的优点和缺点是什么?