common-lisp
Kontrollstrukturen
Suche…
Bedingte Konstrukte
In Common Lisp ist if
das einfachste bedingte Konstrukt. Sie hat die Form (if test then [else])
der then
test
else
(if test then [else])
und wird ausgewertet then
, wenn test
wahr ist und else
nichts anderes. Der else Teil kann weggelassen werden.
(if (> 3 2)
"Three is bigger!"
"Two is bigger!")
;;=> "Three is bigger!"
Ein sehr wichtiger Unterschied zwischen if
in Common Lisp und if
in vielen anderen Programmiersprachen ist, dass CLs if
ein Ausdruck und keine Aussage ist. if
Formulare Werte zurückgeben, die Variablen zugewiesen werden können, werden sie in Argumentlisten verwendet.
;; Use a different format string depending on the type of x
(format t (if (numberp x)
"~x~%"
"~a~%")
x)
Common Lisp's if
kann als äquivalent zu dem ternären Operator angesehen werden: in C # und anderen "geschweiften Klammern".
Beispielsweise der folgende C # -Ausdruck:
year == 1990 ? "Hammertime" : "Not Hammertime"
Entspricht dem folgenden Common Lisp-Code, sofern das year
eine ganze Zahl enthält:
(if (eql year 1990) "Hammertime" "Not Hammertime")
cond
ist ein anderes bedingtes Konstrukt. Es ähnelt einer Kette von if
Anweisungen und hat die Form:
(cond (test-1 consequent-1-1 consequent-2-1 ...)
(test-2)
(test-3 consequent-3-1 ...)
... )
Genauer gesagt, enthält cond
null oder mehr Klauseln , und jede Klausel enthält einen Test, gefolgt von null oder mehr Konsequenzen. Das gesamte cond
Konstrukt wählt die erste Klausel aus, deren Test nicht nil
ergibt, und wertet die Folge davon aus. Es gibt den Wert des letzten Formulars in den Folgen zurück.
(cond ((> 3 4) "Three is bigger than four!")
((> 3 3) "Three is bigger than three!")
((> 3 2) "Three is bigger than two!")
((> 3 1) "Three is bigger than one!"))
;;=> "Three is bigger than two!"
Um eine Standardklausel zu bewerten , wenn keine andere Klausel auswertet t
, können Sie eine Klausel hinzufügen, die standardmäßig mit zutrifft t
. Dies ist in seinem Konzept dem von CASE...ELSE
sehr ähnlich, aber es verwendet eine wörtliche Boolesche Wahrheit anstelle eines Schlüsselworts, um die Aufgabe auszuführen.
(cond
((= n 1) "N equals 1")
(t "N doesn't equal 1")
)
Ein if
Konstrukt kann als cond
Konstrukt geschrieben werden. (if test then else)
und (cond (test then) (t else))
sind gleichwertig.
Wenn Sie nur eine Klausel benötigen, verwenden Sie when
oder unless
:
(when (> 3 4)
"Three is bigger than four.")
;;=> NIL
(when (< 2 5)
"Two is smaller than five.")
;;=> "Two is smaller than five."
(unless (> 3 4)
"Three is bigger than four.")
;;=> "Three is bigger than four."
(unless (< 2 5)
"Two is smaller than five.")
;;=> NIL
Die do-Schleife
Die meisten schleifen- und bedingten Konstrukte in Common Lisp sind eigentlich Makros , die einfachere Konstrukte ausblenden. dotimes
und dolist
basieren beispielsweise auf dem do
Makro. Das Formular für do
sieht folgendermaßen aus:
(do (varlist)
(endlist)
&body)
-
varlist
besteht aus den in der Schleife definierten Variablen, ihren Anfangswerten und wie sie sich nach jeder Iteration ändern. Der Änderungsabschnitt wird am Ende der Schleife ausgewertet. -
endlist
enthält dieendlist
und die am Ende der Schleife zurückgegebenen Werte. Die Endebedingung wird zu Beginn der Schleife ausgewertet.
Hier beginnt man bei 0 und geht bis 10 (nicht einschließlich).
;;same as (dotimes (i 10))
(do (( i (+ 1 i))
((< i 10) i)
(print i))
Und hier ist eine, die sich durch eine Liste bewegt:
;;same as (dolist (item given-list)
(do ((item (car given-list))
(temp list (cdr temp))
(print item))
Der varlist
Teil ist dem einer let
Anweisung ähnlich. Sie können mehrere Variablen binden, die nur in der Schleife vorhanden sind. Jede deklarierte Variable befindet sich in einer eigenen Klammer. Hier ist eine, die zählt, wie viele Einsen und Zweien in einer Liste enthalten sind.
(let ((vars (list 1 2 3 2 2 1)))
(do ((ones 0)
(twos 0)
(temp vars (cdr temp)))
((not temp) (list ones twos))
(when (= (car temp) 1)
(setf ones (+ 1 ones)))
(when (= (car temp) 2)
(setf twos (+ 1 twos)))))
-> (2 3)
Und wenn ein while-Loop-Makro nicht implementiert wurde:
(do ()
(t)
(when task-done
(break)))
Für die häufigsten Anwendungen sind die spezifischeren dotimes
und doloop
Makros viel prägnanter.