common-lisp
Kontrollstrukturer
Sök…
Villkorliga konstruktioner
I Common Lisp, if är den enklaste villkorade konstruktionen. Den har formen (if test then [else]) och utvärderas till then om test är sant och else sätt. Den andra delen kan utelämnas.
(if (> 3 2)
"Three is bigger!"
"Two is bigger!")
;;=> "Three is bigger!"
En mycket viktig skillnad mellan if i Common Lisp och if i många andra programmeringsspråk är att CL: s if är ett uttryck, inte ett uttalande. Som sådan, if formulär returnerar värden, som kan tilldelas variabler, som används i argumentlistor, etc:
;; Use a different format string depending on the type of x
(format t (if (numberp x)
"~x~%"
"~a~%")
x)
Vanliga Lisp if kan betraktas som likvärdiga med den ternära operatören ?: på C # och andra "lockiga stag" -språk.
Till exempel följande C # -uttryck:
year == 1990 ? "Hammertime" : "Not Hammertime"
Är likvärdigt med följande Common Lisp-kod, förutsatt att year har ett heltal:
(if (eql year 1990) "Hammertime" "Not Hammertime")
cond är en annan villkorad konstruktion. Det liknar en kedja av if uttalanden och har formen:
(cond (test-1 consequent-1-1 consequent-2-1 ...)
(test-2)
(test-3 consequent-3-1 ...)
... )
Mer exakt har cond noll eller fler klausuler , och varje klausul har ett test följt av noll eller fler följder. Hela cond konstruktionen väljer den första klausulen vars test inte utvärderar till nil och utvärderar dess följder i ordning. Det returnerar värdet på den sista formen i följdarna.
(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!"
Om du vill tillhandahålla en standardklausul för att utvärdera om ingen annan klausul utvärderas till t kan du lägga till en klausul som är sann som standard med t . Detta är mycket lika i koncept som SQL: s CASE...ELSE , men det använder en bokstavlig booleska sann snarare än ett nyckelord för att utföra uppgiften.
(cond
((= n 1) "N equals 1")
(t "N doesn't equal 1")
)
En if konstruktion kan skrivas som en cond konstruktion. (if test then else) och (cond (test then) (t else)) är likvärdiga.
Om du bara behöver en klausul, använd when eller om 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
Do loopen
De flesta looping och villkorade konstruktioner i Common Lisp är faktiskt makroer som döljer bort mer grundläggande konstruktioner. Till exempel dotimes och dolist på do makroen. Formuläret för do ser ut så här:
(do (varlist)
(endlist)
&body)
-
varlistbestår av variablerna definierade i loopen, deras initiala värden och hur de ändras efter varje iteration. "Ändra" -delen utvärderas i slutet av slingan. -
endlistinnehållerendlistoch värden som returneras i slutet av slingan. Slutvillkoret utvärderas i början av slingan.
Här är en som börjar på 0 och går upp till (inte inklusive) 10.
;;same as (dotimes (i 10))
(do (( i (+ 1 i))
((< i 10) i)
(print i))
Och här är en som går igenom en lista:
;;same as (dolist (item given-list)
(do ((item (car given-list))
(temp list (cdr temp))
(print item))
varlist är lik den i ett let uttalande. Du kan binda mer än en variabel, och de finns bara i slingan. Varje variabel som deklareras finns i sin egen uppsättning parentes. Här är en som räknar hur många 1 och 2 som finns i en lista.
(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)
Och om en makroslinga inte har implementerats:
(do ()
(t)
(when task-done
(break)))
För de vanligaste tillämpningarna är de mer specifika dotimes och doloop mycket mer kortfattade.