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. -
endlistcontiene 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.