【问题标题】:What's the meaning of "#+" in the code of cl-mysql? [duplicate]cl-mysql代码中的“#+”是什么意思? [复制]
【发布时间】:2016-05-03 07:25:36
【问题描述】:

最近我尝试阅读有关cl-mysql 的代码,但被#+ 卡住了。

试过google了,没用,请看这里

(defun make-lock (name)
  #+sb-thread (sb-thread:make-mutex :name name)
  #+ecl (mp:make-lock :name name)
  #+armedbear (ext:make-thread-lock)
  #+ (and clisp mt) (mt:make-mutex :name name)
  #+allegro (mp:make-process-lock :name name))

看起来它适用于不同的后端 lisp 编译器。但仍然不知道为什么要写这样的东西。 谁能帮我说清楚,谢谢。

【问题讨论】:

标签: common-lisp reader-macro


【解决方案1】:

#+ 是一个读取器宏,用于检查关键字是否在特殊变量 *FEATURES* 中。如果它不存在,下面的表格将被跳过(由读者;编译器永远不会看到它)。还有#- 则相反。

有些东西不是 Common Lisp 标准的一部分,但足够重要,以至于所有(或大多数)实现都为它们提供了非标准扩展。当您想在需要处理多个实现的代码中使用它们时,您必须使用读取时条件来为当前实现提供正确的代码。互斥锁(和一般的线程)就是其中之一。

当然,第三方库也可能提供一些功能。 *FEATURES* 的内容如下所示:

(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF-PACKAGE-SYSTEM :ASDF3.1
 :ASDF3 :ASDF2 :ASDF :OS-UNIX :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :64-BIT
 :64-BIT-REGISTERS :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS
 :C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
 :COMPLEX-FLOAT-VOPS :CYCLE-COUNTER :ELF :FLOAT-EQL-VOPS
 :FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT :INLINE-CONSTANTS
 :INTEGER-EQL-VOP :INTERLEAVED-RAW-SLOTS :LARGEFILE :LINKAGE-TABLE :LINUX
 :LITTLE-ENDIAN :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLADDR
 :OS-PROVIDES-DLOPEN :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL
 :OS-PROVIDES-PUTWC :OS-PROVIDES-SUSECONDS-T :PACKAGE-LOCAL-NICKNAMES
 :PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS :SB-DOC :SB-EVAL :SB-FUTEX
 :SB-LDB :SB-PACKAGE-LOCKS :SB-SIMD-PACK :SB-SOURCE-LOCATIONS :SB-TEST
 :SB-THREAD :SB-UNICODE :SBCL :STACK-ALLOCATABLE-CLOSURES
 :STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
 :STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
 :UNIX :UNWIND-TO-FRAME-AND-CALL-VOP :X86-64)

因此,例如,如果您想编写依赖于 Quicklisp 的代码,您可以使用#+quicklisp。如果您想要仅在 Quicklisp 不可用时运行的代码,您可以使用 #-quicklisp

您还可以使用特征的布尔表达式。例如,

#+(or sbcl ecl) (format t "Foo!")

将在 SBCL 或 ECL 上打印 Foo!

#+(and sbcl quicklisp) (format t "Bar!")

只会在具有 Quicklisp 可用的 SBCL 上打印 Bar!

【讨论】:

  • 感谢您的 cmets,真的非常感谢
【解决方案2】:

可以想象我们可以这样写:

(defun make-lock (name)
  (cond ((member :sb-thread *features)
         (sb-thread:make-mutex :name name))
        ((member :ecl *features*)
         (mp:make-lock :name name))
     ...))

但这通常不起作用,因为当它们的包不存在并且某些包是特定于实现/库/应用程序时,我们无法读取符号。包在读取时以惰性/自动方式创建。

在 Common Lisp 中,读取一个不存在的包的符号会导致错误:

CL-USER 1 > (read-from-string "foo:bar")

Error: Reader cannot find package FOO.
  1 (continue) Create the FOO package.
  2 Use another package instead of FOO.
  3 Try finding package FOO again.
  4 (abort) Return to level 0.
  5 Return to top loop level 0.

在您的示例中,sb-thread:make-mutex 是一个在 SBCL 中有意义的符号,但在 Allegro CL 中却没有。此外,Allegro CL 中不存在包 SB-THREAD。因此需要保护 Allegro CL 不被读取。在这种情况下,只有当 sb-thread 出现在 cl:*features* 列表中时,才会读取符号 sb-thread:make-mutex。这可能只适用于 SBCL,或者声称有 sb-threads 可用的 Lisp。

此处的功能表达式可防止 Lisp 尝试读取带有未知包的符号 - 包是未知的,因为相应的软件未加载或不可用。

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 2013-10-06
    • 2015-10-08
    • 2013-05-15
    • 1970-01-01
    • 2018-04-19
    • 2020-07-09
    • 2012-12-11
    • 2012-03-14
    相关资源
    最近更新 更多