2016-05-03 10 views
5

Kürzlich habe ich versucht, Code über cl-mysql zu lesen, aber steckte mit der #+ fest.Was bedeutet "# +" im Code von cl-mysql?

Versuchte es zu googeln, aber nicht arbeiten, so wenden hier

(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)) 

Und sieht aus wie es für verschiedene Backend-Lisp-Compiler ist. Aber immer noch keine Ahnung warum so etwas schreiben soll. Jeder kann mir helfen, es klar zu machen, thx.

+0

Siehe auch: [Common Lisp: Was bedeutet # + nil?] (Http://stackoverflow.com/q/29849954/1281433), [Was bedeutet # + #. bedeutet in Lisp?] (http://Stackoverflow.com/q/5785755/1281433), [Operator # + und # - in .sbclrc] (http://Stackoverflow.com/q/8651695/1281433) –

+1

Ich schloss Dies ist ein Duplikat, da es in anderen Fragen beantwortet wurde, aber ich habe es aufgewertet, weil es ein gutes Beispiel dafür ist, wie diese Konstruktion verwendet wird, und wie Sie festgestellt haben, ist es ziemlich schwierig, danach zu suchen, bis Sie wissen, was es ist aufgerufen (an diesem Punkt müssen Sie normalerweise nicht mehr suchen). –

Antwort

9

#+ ist ein Leser-Makro, das überprüft, ob ein Schlüsselwort in der speziellen Variablen *FEATURES* ist. Wenn es nicht dort ist, wird das folgende Formular übersprungen (vom Leser; der Compiler wird es nie sehen). Es gibt auch #-, die das Gegenteil tut.

Es gibt einige Dinge, die nicht Teil des Common Lisp-Standards sind, aber wichtig genug sind, dass alle (oder die meisten) Implementierungen eine nicht-standardmäßige Erweiterung für sie bieten. Wenn Sie sie in Code verwenden möchten, der für mehrere Implementierungen erforderlich ist, müssen Sie Lesezeitinformationen verwenden, um den richtigen Code für die aktuelle Implementierung bereitzustellen. Mutexes (und Threads im Allgemeinen) sind eines dieser Dinge.

Natürlich können auch Bibliotheken von Drittanbietern zur Verfügung gestellt werden. Der Inhalt *FEATURES* wird wie folgt aussehen:

(: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) 

Also, wenn Sie wollen Code schreiben, zum Beispiel auf Quicklisp abhängig ist, könnten Sie #+quicklisp verwenden. Wenn Sie Code möchten, der nur ausgeführt wird, wenn Quicklisp nicht verfügbar ist, verwenden Sie #-quicklisp.

Sie können auch einen booleschen Ausdruck von Features verwenden. Zum Beispiel würde

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

drucken Foo! entweder SBCL oder ECL.

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

würde nur Bar! auf SBCL drucken, die Quicklisp zur Verfügung hat.

+0

Danke für Ihre Kommentare, wirklich danke – c0rehe110

4

Man könnte sich vorstellen, dass wir schreiben können:

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

Aber das funktioniert in der Regel nicht, weil wir nicht Symbole lesen kann, wenn ihr Paket nicht bestehende und einige Pakete sind Implementierung/library/anwendungsspezifisch. Pakete sind nicht erstellt zur Lesezeit in einer faulen/automatischen Art und Weise.

In Common Lisp, ein Symbol eines Paket zu lesen, das führt nicht existiert, zu einem Fehler:

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. 

In Ihrem Beispiel sb-thread:make-mutex ist ein Symbol, das Gefühl in SBCL macht, aber nicht in Allegro CL . Zusätzlich existiert das Paket SB-THREAD nicht in Allegro CL. Daher muss Allegro CL vor dem Lesen geschützt werden. In diesem Fall wird das Symbol sb-thread:make-mutex nur gelesen, wenn das Merkmal sb-thread in der Liste cl:*features* vorhanden ist. Das ist wahrscheinlich nur für SBCL oder eine Lisp, die sb-threads zur Verfügung hat.

Die Feature-Ausdrücke hier verhindern, dass Lisp versucht, Symbole mit unbekannten Paketen zu lesen - die Pakete sind unbekannt, weil die entsprechende Software nicht geladen oder nicht verfügbar ist.