common-lisp
Besturingsstructuren
Zoeken…
Voorwaardelijke constructen
In Common Lisp is if
het eenvoudigste voorwaardelijke construct. Het heeft de vorm (if test then [else])
en wordt geëvalueerd tot then
of de test
waar is en else
. Het overige deel kan worden weggelaten.
(if (> 3 2)
"Three is bigger!"
"Two is bigger!")
;;=> "Three is bigger!"
Een heel belangrijk verschil tussen if
in Common Lisp en if
in veel andere programmeertalen is dat CL's if
een expressie is, geen statement. Als zodanig, if
vormen retourwaarden, die aan variabelen kan worden toegewezen, gebruikt argumentlijsten, etc:
;; Use a different format string depending on the type of x
(format t (if (numberp x)
"~x~%"
"~a~%")
x)
Gemeenschappelijke Lisp's if
kunnen worden beschouwd als gelijkwaardig aan de ternaire operator?: In C # en andere "gekrulde accolades" talen.
Bijvoorbeeld de volgende C # -uitdrukking:
year == 1990 ? "Hammertime" : "Not Hammertime"
Is gelijk aan de volgende Common Lisp-code, ervan uitgaande dat dat year
een geheel getal heeft:
(if (eql year 1990) "Hammertime" "Not Hammertime")
cond
is een ander voorwaardelijk construct. Het lijkt enigszins op een reeks if
verklaringen en heeft de vorm:
(cond (test-1 consequent-1-1 consequent-2-1 ...)
(test-2)
(test-3 consequent-3-1 ...)
... )
Meer precies, cond
heeft nul of meer clausules en elke clausule heeft één test gevolgd door nul of meer consequenties. Het gehele cond
construct selecteert de eerste clausule waarvan de test niet tot nil
evalueert en evalueert de consequenties in volgorde. Het retourneert de waarde van de laatste vorm in de consequenties.
(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!"
Als u een standaardclausule wilt geven om te evalueren of er geen andere clausule naar t
evalueert, kunt u een standaardclausule toevoegen met t
. Dit is qua concept zeer gelijkaardig aan SQL's CASE...ELSE
, maar het gebruikt een letterlijke booleaanse waarde in plaats van een trefwoord om de taak te volbrengen.
(cond
((= n 1) "N equals 1")
(t "N doesn't equal 1")
)
Een if
constructie kan worden geschreven als een cond
constructie. (if test then else)
en (cond (test then) (t else))
zijn equivalent.
Als u slechts één clausule nodig hebt, gebruik dan when
of 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
De do-lus
De meeste looping- en voorwaardelijke constructen in Common Lisp zijn eigenlijk macro's die meer basale constructies verbergen. dotimes
en dolist
zijn bijvoorbeeld gebaseerd op de do
macro. Het formulier voor do
ziet er als volgt uit:
(do (varlist)
(endlist)
&body)
-
varlist
is samengesteld uit de variabelen die in de lus zijn gedefinieerd, hun beginwaarden en hoe deze na elke iteratie veranderen. Het gedeelte 'wijzigen' wordt geëvalueerd aan het einde van de lus. -
endlist
bevat deendlist
en de waarden die aan het einde van de lus worden geretourneerd. De eindconditie wordt geëvalueerd aan het begin van de lus.
Hier is er een die begint bij 0 en gaat tot (niet inclusief) 10.
;;same as (dotimes (i 10))
(do (( i (+ 1 i))
((< i 10) i)
(print i))
En hier is er een die door een lijst gaat:
;;same as (dolist (item given-list)
(do ((item (car given-list))
(temp list (cdr temp))
(print item))
Het varlist
gedeelte is vergelijkbaar met dat in een let
instructie. U kunt meer dan één variabele binden en deze bestaan alleen binnen de lus. Elke gedeclareerde variabele staat tussen haakjes. Hier is er een die telt hoeveel enen en enen in een lijst.
(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)
En als een while-lusmacro niet is geïmplementeerd:
(do ()
(t)
(when task-done
(break)))
Voor de meest voorkomende toepassingen zijn de meer specifieke dotimes
en doloop
macro's veel beknopter.