Scheme使用单一命名空间来管理所有变量,无论它们是否绑定到函数或其他类型的值。Common Lisp将二者分开,因此标识符“hello”可能在一个上下文中指向函数,在另一个上下文中指向字符串。
(注1:这个问题需要以上内容的示例;请随意编辑并添加一个示例,或通过电子邮件将其发送给原作者,我会这样做。)
但是,在某些情况下,例如将函数作为参数传递给其他函数时,程序员必须显式区分他指定的是函数变量还是非函数变量,使用
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
我一直认为这是一个小瑕疵,但最近我遇到了一个argument,认为这实际上是一个特性:
引用: ......重要的区别实际上在于形式的语法,而不在于对象的类型。在不知道涉及的运行时值的情况下,很明显函数形式的第一个元素必须是函数。CL利用这一事实,并将其与宏和特殊形式一起成为语言的一部分,这些形式也可以(并且必须)静态确定。那么我的问题是:当函数名称的主要用途是出现在不太可能出现变量名称的地方时,为什么要将函数名称和变量名称放在同一个命名空间中?
考虑类名的情况:为什么名为 FOO 的类会阻止使用名为 FOO 的变量?我只有在期望类名的上下文中才会用到名为 FOO 的类。如果极少数情况下需要获取绑定到类名 FOO 的类对象,则可以使用 FIND-CLASS。从我的经验来看,这个论点确实有些道理;Haskell 中也有类似的情况,字段名称也是用于访问字段的函数。这有点尴尬:
(注1:这个问题需要以上内容的示例;请随意编辑并添加一个示例,或通过电子邮件将其发送给原作者,我会这样做。)
但是,在某些情况下,例如将函数作为参数传递给其他函数时,程序员必须显式区分他指定的是函数变量还是非函数变量,使用
#'
,如下所示:(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
我一直认为这是一个小瑕疵,但最近我遇到了一个argument,认为这实际上是一个特性:
引用: ......重要的区别实际上在于形式的语法,而不在于对象的类型。在不知道涉及的运行时值的情况下,很明显函数形式的第一个元素必须是函数。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中,以及一般情况下,一个命名空间包含所有值与分开为函数和非函数值各自拥有命名空间的优缺点是什么?