Recherche…


Constructions conditionnelles

Dans Common Lisp, if est la construction conditionnelle la plus simple. Il a la forme (if test then [else]) le then test else (if test then [else]) et est évaluée pour then si test est vrai et d' else autrement. Le reste peut être omis.

(if (> 3 2)
    "Three is bigger!"
    "Two is bigger!")
;;=> "Three is bigger!"

Une différence très importante entre if dans Common Lisp et if dans de nombreux autres langages de programmation, CL est if une expression, pas une déclaration. En tant que tels, if formulaires renvoient des valeurs pouvant être affectées à des variables, utilisées dans les listes d'arguments, etc.:

;; Use a different format string depending on the type of x
(format t (if (numberp x)
              "~x~%"
              "~a~%")
           x)

De Common Lisp if peut être considéré comme équivalent à l' opérateur ternaire: en C # et d' autres langues « accolade ».

Par exemple, l'expression C # suivante:

year == 1990 ? "Hammertime" : "Not Hammertime"

Est équivalent au code Common Lisp suivant, en supposant que cette year contient un entier:

(if (eql year 1990) "Hammertime" "Not Hammertime")

cond est une autre construction conditionnelle. Il est quelque peu similaire à une chaîne de déclarations if et a la forme:

(cond (test-1 consequent-1-1 consequent-2-1 ...)
      (test-2)
      (test-3 consequent-3-1 ...)
      ... )

Plus précisément, cond a zéro ou plusieurs clauses , et chaque clause a un test suivi de zéro ou plusieurs conséquences. L'ensemble de la construction cond sélectionne la première clause dont le test n'est pas évalué à nil et évalue ses conséquences dans l'ordre. Il renvoie la valeur de la dernière forme dans les conséquents.

(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!"

Pour fournir une clause par défaut à évaluer si aucune autre clause n'équivaut à t , vous pouvez ajouter une clause qui est vraie par défaut à l'aide de t . Ce concept est très similaire au concept CASE...ELSE de SQL, mais il utilise un booléen littéral true plutôt qu'un mot-clé pour accomplir la tâche.

(cond
    ((= n 1) "N equals 1")
    (t "N doesn't equal 1")
)

Une construction if peut être écrite comme une construction cond . (if test then else) et (cond (test then) (t else)) sont équivalents.

Si vous n'avez besoin que d'une clause, utilisez when ou à 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

La boucle do

La plupart des constructions en boucle et conditionnelles dans Common Lisp sont en fait des macros qui cachent des constructions plus basiques. Par exemple, les dotimes et dolist sont construits sur la macro do . Le formulaire pour do ressemble à ceci:

(do (varlist)
    (endlist)
   &body)
  • varlist est composée des variables définies dans la boucle, de leurs valeurs initiales et de leur modification après chaque itération. La partie 'change' est évaluée à la fin de la boucle.
  • endlist contient les conditions de fin et les valeurs renvoyées à la fin de la boucle. La condition de fin est évaluée au début de la boucle.

En voici un qui commence à 0 et va jusqu'à (non compris) 10.

;;same as (dotimes (i 10)) 
(do (( i (+ 1 i))
    ((< i 10) i)
   (print i))

Et en voici un qui se déplace dans une liste:

;;same as (dolist (item given-list)
(do ((item (car given-list))
     (temp list (cdr temp))
   (print item))

La partie varlist est similaire à celle d'une instruction let . Vous pouvez lier plusieurs variables et elles n'existent que dans la boucle. Chaque variable déclarée est dans son propre ensemble de parenthèses. En voici un qui compte combien de 1 et 2 sont dans une liste.

(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)

Et si une macro de boucle while n'a pas été implémentée:

(do ()
    (t)
  (when task-done
    (break)))

Pour les applications les plus courantes, les macros dotimes et doloop plus spécifiques sont beaucoup plus succinctes.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow