代码之家  ›  专栏  ›  技术社区  ›  MadPhysicist

当全局声明space special时,违反了包common-lisp上的锁

  •  2
  • MadPhysicist  · 技术社区  · 7 年前

    我曾试图在SBCL的顶部做类似的事情:

    CL-USER> (defvar space " ")
    

    我得到的错误是

    Lock on package COMMON-LISP violated when
    globally declaring SPACE SPECIAL while in package
    COMMON-LISP-USER.
       [Condition of type SYMBOL-PACKAGE-LOCKED-ERROR]
    
    Restarts:
     0: [CONTINUE] Ignore the package lock.
     1: [IGNORE-ALL] Ignore all package locks in the context of this operation.
     2: [UNLOCK-PACKAGE] Unlock the package.
     3: [RETRY] Retry SLY mREPL evaluation request.
     4: [*ABORT] Return to SLY's top level.
     5: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {10025F6303}>)
    
    Backtrace:
      0: (PACKAGE-LOCK-VIOLATION #<PACKAGE "COMMON-LISP"> :SYMBOL SPACE :FORMAT-CONTROL "globally declaring ~A ~A" :FORMAT-ARGUMENTS (SPACE SPECIAL))
      1: (SB-KERNEL:ASSERT-SYMBOL-HOME-PACKAGE-UNLOCKED SPACE "globally declaring ~A ~A" SPECIAL)
      2: (SB-C::PROCESS-VARIABLE-DECLARATION SPACE SPECIAL :SPECIAL)
      3: ((LABELS SB-C::MAP-NAMES :IN SB-C::%PROCLAIM) (SPACE) #<FUNCTION SB-C::PROCESS-VARIABLE-DECLARATION> SPECIAL :SPECIAL)
      4: (PROCLAIM (SPECIAL SPACE))
      5: (SB-IMPL::%DEFVAR SPACE #S(SB-C:DEFINITION-SOURCE-LOCATION :NAMESTRING NIL :INDICES 0) " " NIL)
      6: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SB-IMPL::%DEFVAR (QUOTE SPACE) (SB-C:SOURCE-LOCATION) (UNLESS (BOUNDP #) " ")) #<NULL-LEXENV>)
      7: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DEFVAR SPACE " ") #<NULL-LEXENV>)
      8: (EVAL (DEFVAR SPACE " "))
      9: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
     --more--
    

    但是,当我试图检查 space 在中定义 CL-USER 包裹,它告诉我它不是。

    The variable SPACE is unbound.
       [Condition of type UNBOUND-VARIABLE]
    
    Restarts:
     0: [CONTINUE] Retry using SPACE.
     1: [USE-VALUE] Use specified value.
     2: [STORE-VALUE] Set specified value and use it.
     3: [RETRY] Retry SLY mREPL evaluation request.
     4: [*ABORT] Return to SLY's top level.
     5: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {10025F6303}>)
    
    Backtrace:
      0: (SB-INT:SIMPLE-EVAL-IN-LEXENV SPACE #<NULL-LEXENV>)
      1: (EVAL SPACE)
      2: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
     --more--
    

    为什么会这样?如果在包中的“space”一词上有一个锁,为什么要解除它的绑定?

    2 回复  |  直到 7 年前
        1
  •  8
  •   Steve Losh    7 年前

    第一: SPACE is an external symbol in the COMMON-LISP package 按照标准。它不是作为变量或函数绑定的,但它是声明中使用的符号,例如 (declare (optimize (speed 2) (space 0))) .

    第二个: there are a lot of things you're not allowed to do to external symbols in the COMMON-LISP package . 该标准表示结果未定义,在这种情况下,大多数实现将选择发出错误信号。尤其是10号咬你的东西:

    1. 宣布或宣布它特别

    因为 (defvar foo ...) 宣告 foo 特殊。

    所以你为什么不能回答 (defvar space ...) 是因为 空间 是的外部符号 通用LISP 包裹。它是否具有函数/变量绑定并不重要,这些限制适用于 全部的 中的外部符号 通用LISP .

    能够 通过阴影来绕过这个 空间 在你的包裹里。然后 空间 你所宣称的特别的符号不是 通用LISP 包,但您自己包中的包(恰好有相同的名称)。但这仍然是不好的风格。 You should pretty much always use earmuffs around special variables. (defvar *space* " ") 会很好的工作(因为 *space* 中不是外部符号 通用LISP )还有一个好处就是不会混淆任何试图阅读代码的人(因为我们期待特殊变量的耳罩)。

        2
  •  5
  •   Rainer Joswig mmmmmm    7 年前

    但是,当我试图检查并查看cl-user包中是否定义了空间时,它告诉我它不是。

    发生错误不是因为您试图操作符号 space 包装内 CL-USER 但是一个符号 空间 在里面 CL ,可在 CL-用户 .

    检查符号是否未绑定与检查其主包不同。

    有名字的符号吗 空间 在包裹里 (阿卡 COMMON-LISP )?

    CL-USER 125 > (find-symbol "SPACE" "CL")
    SPACE
    :EXTERNAL
    

    在cl包中有许多未绑定的符号。