【问题标题】:Why are uninterned symbols used for package names and exports in Common Lisp?为什么 Common Lisp 中的包名称和导出使用非内部符号?
【发布时间】:2011-12-15 05:23:23
【问题描述】:

在 Common List 上的 screen cast 中,作者对包名和导出使用了非内部符号。

(defpackage #:foo
  (:use :cl)
  (:export #:bar
           #:baz))

(in-package #:foo)

他还在匿名函数前使用尖号。

(defun transposed (m)
  (make-instance 'matrix
                 :rows (matrix-cols m)
                 :cols (matrix-rows m)
                 :generator #'(lambda (i j) (matrix-at m j i))))

据我所知,在Practical Common Lisp 书中,尖号不用于包名称和导出。

在这些情况下使用非驻留符号(尖号)的原因是什么?

【问题讨论】:

    标签: lisp common-lisp symbols


    【解决方案1】:

    使用实习符号会污染您当前所在的包,其中的符号无论如何仅用于其名称:

    [1]> *package*
    #<PACKAGE COMMON-LISP-USER>
    [2]> (defpackage bar)
    #<PACKAGE BAR>
    [3]> (find-symbol "BAR")
    BAR ;
    :INTERNAL
    

    Uninterned 符号不会这样做:

    ;; Uninterned symbols don't cause symbol pollution:
    [4]> (defpackage #:foo)
    #<PACKAGE FOO>
    [5]> (find-symbol "FOO")
    NIL ;
    NIL
    

    你也可以直接使用字符串,但是由于你通常处理的是大写的符号名,它们写起来不太方便:

    [6]> (defpackage "BARFOO")
    #<PACKAGE BARFOO>
    [7]> (find-symbol "BARFOO")
    NIL ;
    NIL
    

    示例

    为了说明问题,请考虑以下交互:

    [1]> (defpackage hello (:use cl) (:export hello))
    #<PACKAGE HELLO>
    
    ;; Let's write some FOO stuff...
    [2]> (defpackage foo (:use cl))
    #<PACKAGE FOO>
    [3]> (in-package foo)
    #<PACKAGE FOO>
    
    ;; Oh, I forgot to import HELLO!
    ;; Let's fix that.
    FOO[4]> (defpackage foo (:use cl hello))
    *** - (COMMON-LISP:USE-PACKAGE (#<PACKAGE HELLO> #<PACKAGE COMMON-LISP>)
          #<PACKAGE FOO>): 1 name conflicts remain
          Which symbol with name "HELLO" should be accessible in #<PACKAGE FOO>?
    
    ;; Oops.
    

    【讨论】:

    • 所以写(dotimes (#:i 10) (print "Woa"))这样的东西被认为更干净?
    • @6502 这是一个有趣的案例。 :) 有点不同,因为dotimes 表单通常位于in-package 表单下方的某个位置,因此它将始终在指定的包中读取。污染并没有那么糟糕——不管怎样,你总是这样做。 defpackagein-package 在这方面比较麻烦,因为当读取相应的表格时,很难预测你会污染哪些包裹;毕竟,它可能发生在任何时间,或多或少发生在任何地方,尤其是在进行交互式开发时。
    • 是的……想了一会儿,我认为你的答案是正确的。当一个符号 ONLY 用于它的名字时,最好使用一个非内部符号。它还与“现代模式”IIRC 配合得更好。
    • 有人在lambdas 前面解决了关于#' 的OP 问题吗?我不知道在哪里可以使用#'(lambda (...) ...),而不是使用(lambda (...) ...)
    • @Dietrich 但是(defpackage :foo) 确实在KEYWORD 包中留下了一个符号FOO。在(defpackage :foo) 之后,(find-symbol "FOO" "KEYWORD") 返回:FOO:EXTERNAL
    【解决方案2】:

    #'function 运算符的简写(在 Practical Common Lisp 书中多次使用)。

    【讨论】:

    • 不,它与管道无关,与使用符号作为其名称而不是其身份有关。
    • @jeha,你是对的 #' 用于 Practical Common Lisp。我已经解决了这个问题。
    猜你喜欢
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 2020-01-07
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多