代码之家  ›  专栏  ›  技术社区  ›  Vijay Mathew Chor-ming Lung

为什么有多个名称空间?

  •  13
  • Vijay Mathew Chor-ming Lung  · 技术社区  · 14 年前

    在公共Lisp中为值和函数设置单独的名称空间的设计决策背后的基本原理是什么?支持和反对它的理由是什么?

    5 回复  |  直到 10 年前
        1
  •  8
  •   Zorf    14 年前

    普通的lisp基本上是源于原始lisp 1.5的后代,或者更确切地说,是其分散方言的统一体。最初的Lisp 1.5现在被称为Lisp-2。因为它早在60年代,你可以把函数传递给其他函数这一事实已经够奇怪了。没有人会考虑让他们共享相同的名称空间。如今,几乎所有支持高阶函数和匿名函数的语言都选择单名称空间方法。包括Clojure,它在其他方面更接近普通Lisp而不是Scheme。

    和clojure一样,scheme最初并不是一种与lisp 1.5不同的方言,出于它们的目的,它是有意义的。

    当然,在clojure中,向量、散列图、集合以及所有可以应用于参数的东西,所以在某种意义上,clojure中的向量可以被看作是一个函数,它接受自然数并从中产生一个值。

        2
  •  16
  •   Greg Hewgill    14 年前

    请看理查德·加布里埃尔的论文 Technical Issues of Separation in Function Cells and Value Cells 对这门学科进行全面的学术研究。

        3
  •  7
  •   JasonFruit    14 年前

    虽然理论上可能有很多不同的论点,但我敢打赌,这在很大程度上是哲学的起源。Scheme是一个lisp-1,它更喜欢优雅而不是实用性,并且选择了同样的风格。 define 变量和函数的语法,使单个名称空间感觉自然(并鼓励使用函数式编程)。普通的Lisp倾向于实用性和强大性而不是优雅性,并且是一种构建共识的尝试,因此看到一个现有的两个名称空间解决方案被广泛接受并且工作良好,就接受了它。

    然而,在实践中,它主要意味着三件事:

    • 在普通Lisp(和其他Lisp-2)中,必须使用 funcall 很多
    • 在方案(和其他lisp-1)中,必须注意不要重写 需要带变量的函数名;例如函数参数 lst 而不是 list
    • 在互联网上,会有争论

    然而,这是一些人喜欢一个口齿不清的主要原因之一。

        4
  •  4
  •   lnostdal    14 年前

    实际上,我喜欢有多个名称空间(甚至超过两个);它使用户和编译器编写器(实现)更容易:

    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> 
    
        5
  •  0
  •   John Cowan    10 年前

    除了上面提到的其他问题之外,拥有一个单独的函数名称空间使得cl不卫生的宏更不可能攻击宏用户。在cl中,在调用点绑定的、出现在宏扩展中的名称将在调用点使用定义, 定义宏时使用的定义。因此,在cl的lisp-1版本中,如果宏扩展到对list函数的调用,并且list被定义为调用宏的点的变量,那么宏就会失效。(注意gensyms并不能解决这个问题,不像他们解决的逆问题。)

    在Scheme中不会发生这种情况,因为默认情况下,Scheme宏是卫生的:宏扩展中使用的所有名称都具有定义宏的位置所具有的含义,而不是宏的使用位置。