Buscar..


Construcciones condicionales

En Common Lisp, if es la construcción condicional más simple. Tiene la forma (if test then [else]) y se evalúa a then si la test es verdadera y de else contrario. La otra parte puede ser omitida.

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

Una diferencia muy importante entre if en Common Lisp y if en muchos otros lenguajes de programación es que CL de if es una expresión, no una afirmación. Como tal, if formularios devuelven valores, que pueden asignarse a variables, usarse en listas de argumentos, etc.

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

Common Lisp 's if se puede considerar equivalente al operador ternario?: En C # y otros lenguajes de "corsé".

Por ejemplo, la siguiente expresión de C #:

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

Es equivalente al siguiente código Common Lisp, asumiendo que ese year contiene un número entero:

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

cond es otro constructo condicional. Es algo similar a una cadena de sentencias if , y tiene la forma:

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

Más precisamente, cond tiene cero o más cláusulas , y cada cláusula tiene una prueba seguida de cero o más consecuentes. La construcción completa de cond selecciona la primera cláusula cuya prueba no evalúa a nil y evalúa sus consecuentes en orden. Devuelve el valor del último formulario en los consecuentes.

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

Para proporcionar una cláusula predeterminada para evaluar si ninguna otra cláusula se evalúa como t , puede agregar una cláusula que sea verdadera de manera predeterminada utilizando t . Este concepto es muy similar al de CASE...ELSE de SQL CASE...ELSE , pero utiliza un verdadero booleano literal en lugar de una palabra clave para realizar la tarea.

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

Una construcción if puede escribirse como una construcción cond . (if test then else) y (cond (test then) (t else)) son equivalentes.

Si solo necesita una cláusula, use when o a 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

El bucle do

La mayoría de las construcciones condicionales y de bucle en Common Lisp son en realidad macros que ocultan construcciones más básicas. Por ejemplo, dotimes y dolist se basan en la macro do . La forma para do ve así:

(do (varlist)
    (endlist)
   &body)
  • varlist se compone de las variables definidas en el bucle, sus valores iniciales y cómo cambian después de cada iteración. La parte de 'cambio' se evalúa al final del bucle.
  • endlist contiene las condiciones finales y los valores devueltos al final del bucle. La condición final se evalúa al comienzo del bucle.

Aquí hay uno que comienza en 0 y sube hasta (no incluye) 10.

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

Y aquí hay uno que se mueve a través de una lista:

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

La parte varlist es similar a la de una sentencia let . Puede enlazar más de una variable, y solo existen dentro del bucle. Cada variable declarada está en su propio conjunto de paréntesis. Aquí hay uno que cuenta cuántos 1 y 2 están en 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)

Y si una macro loop de while no ha sido implementada:

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

Para las aplicaciones más comunes, las macros dotimes y doloop más específicas son mucho más sucintas.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow