Common Lisp与Scheme中函数和变量的单独命名空间

时间:2009-06-20 04:51:31

标签: variables scheme lisp common-lisp lisp-2

Scheme对所有变量使用单个命名空间,无论它们是绑定到函数还是其他类型的值。 Common Lisp将两者分开,这样标识符“hello”可以引用一个上下文中的函数,而另一个上下文中的字符串。

(注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 vs. Scheme以及一般来说,所有值的单个命名空间与函数和非函数值的单独命名空间有哪些优点和缺点?

6 个答案:

答案 0 :(得分:22)

两种不同的方法有名称:Lisp-1和Lisp-2。 Lisp-1对变量和函数都有一个命名空间(如在Scheme中),而Lisp-2有变量和函数的独立命名空间(如在Common Lisp中)。我之所以提到这一点是因为你可能没有注意到这个术语,因为你没有在你的问题中提到它。

维基百科refers to this debate

  

函数的单独命名空间是否有优势是Lisp社区中的争用来源。它通常被称为Lisp-1 vs. Lisp-2辩论。 Lisp-1指的是Scheme的模型,Lisp-2指的是Common Lisp的模型。这些名字是由Richard P. Gabriel和Kent Pitman撰写的1988年论文中创造的,后者对这两种方法进行了广泛的比较。

加布里埃尔和皮特曼的论文Technical Issues of Separation in Function Cells and Value Cells解决了这个问题。

答案 1 :(得分:11)

实际上,正如the paper by Richard Gabriel and Kent Pitman中所述,争论是针对Lisp-5的Lisp-5,因为已经存在其他几个名称空间,本文中提到了类型名称,标签名称,块名称和声明名称。 编辑:这似乎是不正确的,正如Rainer在评论中指出的那样:Scheme实际上似乎是一个Lisp-1。但是,以下内容在很大程度上不受此错误的影响。

符号表示要执行的内容或要引用的内容始终从上下文中清楚。将函数和变量抛出到同一名称空间主要是一个限制:程序员不能对事物和动作使用相同的名称。 Lisp-5从中得到的只是避免了从当前上下文暗示的不同命名空间引用某些东西的语法开销。 编辑:这不是整个图片,只是表面。

我知道Lisp-5的支持者喜欢函数是数据的事实,而这是在语言核心中表达的。我喜欢这样一个事实:我可以在不混淆编译器的情况下调用列表“列表”和汽车“汽车”,而且函数无论如何都是一种基本上特殊的数据。 编辑:这是我的主要观点:单独的命名空间根本不是疣。

我也很喜欢what Pascal Constanza had to say

答案 2 :(得分:2)

我在Python(统一命名空间)和Ruby(方法与非方法的不同命名空间)中遇到了类似的区别。在这种情况下,我更喜欢Python的方法 - 例如,使用这种方法,如果我想列出一些事物,其中一些是函数,而另一些则不是,我不需要做任何与它们名称不同的事情。例如,取决于他们的“功能性”。类似的考虑适用于所有情况,其中函数对象被绑定而不是被调用(参数,并从高阶函数返回值等等)。

也可以调用非函数(如果它们的类定义__call__,在Python的情况下 - “运算符重载”的特殊情况)因此“上下文区别”不一定清楚,任

然而,我的“lisp-oid”体验主要是使用Scheme而不是Common Lisp,所以我可能会因熟悉统一命名空间而潜意识地偏向于最终来自该体验。

答案 3 :(得分:1)

Scheme中函数的名称只是一个函数作为其值的变量。无论我是(define x (y) (z y))还是(let ((x (lambda (y) (z y)))),我都在定义一个我可以调用的函数。因此,就“方案”而言,“变量名很少想出现在那里”这一想法是一种似是而非。

Scheme是一种特色功能语言,因此将函数视为数据是其原则之一。将函数作为自己的一种类型,与所有其他数据一样存储是一种继承理念的方式。

答案 4 :(得分:1)

我看到的最大缺点,至少对于Common Lisp来说,是可理解性。我们都同意它对变量和函数使用不同的命名空间,但它有多少?在PAIP中,Norvig表明它具有“至少七个”命名空间。

当一位由一位备受尊敬的程序员撰写的语言经典书籍之一甚至无法在出版的书中说出来时,我认为存在问题。我对多个名称空间没有任何问题,但我希望该语言至少足够简单,某人可以完全理解它的这一方面。

我很乐意为变量和函数使用相同的符号,但是在更加模糊的区域中,我会因恐惧而使用不同的名称(碰撞名称空间可能很难调试!),这真的应该从来不是这样。

答案 5 :(得分:0)

两种方法都有好处。但是,我发现当它重要时,我更喜欢同时使用函数LIST和变量LIST,而不是错误拼写其中一个。