Frage

Ich arbeite durch Practical Common Lisp und als eine Übung beschlossen, ein Makro zu schreiben, um festzustellen, ob eine Zahl ist ein Vielfaches einer anderen Zahl:

(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))

, so dass: (multp 40 10) true ausgewertet, während (multp 40 13) nicht

Die Frage ist tut das Makro Leck in irgendeiner Weise? Auch das ist „gut“ Lisp? Gibt es bereits eine bestehende Funktion / Makro, die ich verwendet haben?

War es hilfreich?

Lösung

Siebel gibt einen umfassenden Überblick (in einfachen Fällen sowieso) von möglichen Quellen von Leckagen, und es gibt nicht irgendwelche von denen hier. Sowohl value und factor werden nur einmal ausgewertet und in Ordnung, und rem hat keine Nebenwirkungen.

Das ist aber nicht gut Lisp, denn es gibt keinen Grund, einen Makro in diesem Fall zu verwenden. Eine Funktion

(defun multp (value factor)
  (zerop (rem value factor)))

ist identisch für alle praktischen Zwecke. (Beachten Sie die Verwendung von zerop. Ich denke, es macht die Dinge klarer in diesem Fall, aber in Fällen, in denen Sie hervorheben müssen, dass der Wert, den Sie testen noch sinnvoll sein könnte, wenn es etwas anderes ist dann Null, (= ... 0) könnte besser sein)

Andere Tipps

Ihr Makro sieht für mich in Ordnung. Ich weiß nicht, was ein undichtes Makro ist, aber bei Ihnen ist ziemlich einfach und erfordert keine gensyms. Soweit wenn dies „gut“ Lisp, Faust meine Regel ist nur ein Makro zu verwenden, wenn eine Funktion nicht tun wird, und in diesem Fall eine Funktion kann anstelle des Makros verwendet werden. Wenn jedoch diese Lösung für Sie gibt es keinen Grund, es nicht zu benutzen.

Nun, im Prinzip könnte ein Benutzer dies tun:

(flet ((= (&rest args) nil))
  (multp 40 10))

, die zu NIL bewerten würde ... außer, dass ANSI CL macht es illegal die meisten Standard-Symbole erneut zu binden, einschließlich CL:. =, So dass Sie auf der sicheren Seite in diesem speziellen Fall sind

In generial, natürlich, sollten Sie sich bewusst sowohl Referenz Undurchlässigkeitspegel sein (Kennungen aus dem Kontext die Erfassung der Makro in erweitert wird) und Makro unhygiene (Identifikatoren erweiterte Code undicht).

Nein, kein Symbol in der Makros „lexikalische Schließung“ eingeführt wird, nach außen abgegeben.

Beachten Sie, dass undichte nicht unbedingt eine schlechte Sache ist, auch wenn ein versehentliches Auslaufen fast immer. Für ein Projekt, das ich arbeitete, fand ich, dass ein Makro ähnlich war nützlich:

(defmacro ana-and (&rest forms)
  (loop for form in (reverse forms)
        for completion = form then `(let ((it ,form))
                                      (when it
                                       ,completion))
        finally (return completion)))

Die erlaubte mir, „Kurzschluss“ der Dinge zu bekommen benötigen nacheinander durchgeführt werden, mit Argumenten aus früheren Aufrufen in der Folge (und ein Ausfall durch Rücksendung NIL signalisiert) übertragen. Der spezifische Kontext von diesem Code ist für einen handgeschriebenen Parser für eine Konfigurationsdatei, die eine gepflasterte-together-genug Syntax hat, die einen geeigneten Parser schriftlich unter Verwendung eines Parser-Generators war mehr Arbeit als Handwalzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top