common-lisp
Strutture di controllo
Ricerca…
Costrutti condizionali
In Common Lisp, if
è il costrutto condizionale più semplice. Ha il modulo (if test then [else])
e viene valutato per then
se test
è vero e else
altrimenti. La parte else può essere omessa.
(if (> 3 2)
"Three is bigger!"
"Two is bigger!")
;;=> "Three is bigger!"
Una differenza molto importante tra if
in Common Lisp e if
in molti altri linguaggi di programmazione è che CL if
è un'espressione, non un'istruzione. Di conseguenza, if
moduli restituiscono valori, che possono essere assegnati a variabili, utilizzati negli elenchi di argomenti, ecc.
;; Use a different format string depending on the type of x
(format t (if (numberp x)
"~x~%"
"~a~%")
x)
Common Lisp's if
può essere considerato equivalente all'operatore ternario?: In C # e in altre lingue "parentesi graffe".
Ad esempio, la seguente espressione C #:
year == 1990 ? "Hammertime" : "Not Hammertime"
È equivalente al seguente codice Common Lisp, assumendo che year
un intero:
(if (eql year 1990) "Hammertime" "Not Hammertime")
cond
è un altro costrutto condizionale. È in qualche modo simile a una catena di istruzioni if
e ha la forma:
(cond (test-1 consequent-1-1 consequent-2-1 ...)
(test-2)
(test-3 consequent-3-1 ...)
... )
Più precisamente, cond
ha zero o più clausole e ogni frase ha un test seguito da zero o più conseguenti. L'intero cond
costrutto seleziona la prima clausola il cui test non valuta nil
e valuta i suoi conseguenti nell'ordine. Restituisce il valore dell'ultima forma nei conseguenti.
(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!"
Per fornire una clausola predefinita per valutare se nessun'altra clausola restituisce t
, è possibile aggiungere una clausola vera per default usando t
. Questo concetto è molto simile a quello di SQL CASE...ELSE
, ma usa un vero valore booleano letterale piuttosto che una parola chiave per eseguire l'operazione.
(cond
((= n 1) "N equals 1")
(t "N doesn't equal 1")
)
Un costrutto if
può essere scritto come costrutto cond
. (if test then else)
e (cond (test then) (t else))
sono equivalenti.
Se hai solo bisogno di una clausola, usa when
o 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
Il ciclo di do
La maggior parte dei loop e condizionali costrutti in Common Lisp sono in realtà le macro che nascondono via costrutti più basilari. Ad esempio, dotimes
e dolist
sono costruiti sul do
macro. Il modulo per do
aspetto:
(do (varlist)
(endlist)
&body)
-
varlist
è composta dalle variabili definite nel ciclo, i loro valori iniziali, e come cambiano dopo ogni iterazione. La porzione 'cambiamento' viene valutata alla fine del ciclo. -
endlist
contiene le condizioni finali e valori restituiti al termine del ciclo. La condizione finale viene valutata all'inizio del ciclo.
Ecco uno che inizia a 0 e va fino a (ad esclusione di) 10.
;;same as (dotimes (i 10))
(do (( i (+ 1 i))
((< i 10) i)
(print i))
Ed ecco uno che si muove attraverso una lista:
;;same as (dolist (item given-list)
(do ((item (car given-list))
(temp list (cdr temp))
(print item))
La porzione varlist
è simile a quella in una dichiarazione let
. È possibile associare più di una variabile e esistono solo all'interno del ciclo. Ogni variabile dichiarata è racchiusa tra parentesi. Ecco uno che conta quanti 1 e 2 sono in una 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)
E se una macro del ciclo while non è stata implementata:
(do ()
(t)
(when task-done
(break)))
Per le applicazioni più comuni, i più specifici dotimes
e doloop
macro sono molto più succinta.