layout | title | permalink |
---|---|---|
default |
Control de Flujo |
/es/outline/flow_control.html |
{::options parse_block_html="true" /}
{% comment %}
http://clojurebridge.github.io/curriculum/es/outline/flow_control.html
{% endcomment %}
if
cond
- Lógica booleana
"Control de Flujo" es el término usado en programación para decidir cómo reaccionar ante una dada circunstancia. Tomamos decisiones de esta manera todo el tiempo. Si (if) es un lindo día, entonces (then) deberíamos ir la parque. Si no (else) deberíamos quedarnos y jugar juegos de mesa. Si el tanque está vacío, entonces deberías ir a cargar nafta, si no deberías continuar hasta tu lugar de destino. {: ng-show="block11" .description}
El software está lleno de este tipo de decisiones. Si el input del usuario es válido, entonces guardamos sus datos; si no le mostramos un mensaje de error. El patrón común es que verificás una condición y reaccionás de forma diferente basado en si la condición da verdadero (true) o falso (false). {: ng-show="block12" .description}
En Clojure, la herramienta más básica que tenemos para Control de Flujo es el operador if. Acá hay un ejemplo de cómo podrías programar un escenario de validación de ciertos datos de entrada: {: ng-show="block21" .description}
Ejemplo: Si luego de sumar 40 a
y
da menos de 150, entonces se debe retornar(+ y 40)
; si no, retornar -150. (esto es para la app de la tortuga, el borde superior del marco está en 150 en y, y el inferior en -150 en y.) {: ng-show="block22" .description}
Referencia: Condicional
if
{: ng-show="block22" .description}
(if (< (+ y 40) 150)
(+ y 40)
-150))
(if conditional-expression
expression-to-evaluate-when-true
expression-to-evaluate-when-false)
(if (> 3 1)
"3 es mayor que 1"
"3 no es mayor que 1")
;=> "3 es mayor que 1"
(if (> 1 3)
"1 es mayor que 3"
"1 no es mayor que 3")
;=> "1 no es mayor que 3"
Al testear el valor de verdad de una expresión, Clojure considera los valores
nil
yfalse
como falso y cualquier otro valor como verdadero. Acá hay algunos ejemplos: {: ng-show="block51" .description}
Referencia: Truthiness/Valor de verdad {: ng-show="block51" .description}
(if "cualquier valor aparte de nil y false es considerado verdadero"
"Un string es considerado verdadero"
"Un string no es considerado verdadero")
;=> "Un string es considerado verdadero"
(if nil
"nil es considerado verdadero"
"nil no es considerado verdadero")
;=> "nil no es considerado verdadero"
(if (get {:a 1} :b)
"las expresiones que evalúan a nil son consideradas verdaderas"
"las expresiones que evalúan a nil no son consideradas verdaderas")
;=> "las expresiones que evalúan a nil no son consideradas verdaderas"
-
Escribir una función
y-within-frame
que recibe y (posición vertical) como argumento. -
Podés usar alguno de los ejemplos de if del slide.
-
La función debe devolver un valor de y que no sea mayor a 150.
;; ejemplo de if
(if (< (+ y 40) 150)
(+ y 40)
-150))
;; uso de la función y-within-frame
(y-within-frame 80) ;=> 120
(y-within-frame 180) ;=> -150
El operador
if
toma un sólo predicado. Cuando queremos usar múltiples predicados,if
no es una buena opción. Tenemos que anidar, anidar... y anidar condicionesif
. Para contemplar múltiples situaciones, el operadorcond
funciona bien. {: ng-show="block61" .description}
Acá va el ejemplo. Si sumando 40 a
y
da más que 150, evaluar la primer forma. En este caso, devuelve -150. Si sumando 40 ay
da menos que -150, evaluar la segunda forma. En este caso, devuelve 150. Si los dos predicados retornan falso, evaluar la forma:else
. In este caso, retornay
más 40. Si usamos esta función en la app de la tortuga, podemos mantener a nuestra tortuga entre el borde superior e inferior del marco. {: ng-show="block62" .description}
Referencia: Condicional
cond
{: ng-show="block62" .description}
(cond
(> (+ y 40) 150) -150
(< (+ y 40) -150) 150
:else (+ y 40)))
(cond
predicate1 expression-to-evaluate-when-predicate1-is-true
predicate2 expression-to-evaluate-when-predicate2-is-true
...
:else expression-to-evaluate-when-all-above-are-false)
La función que escribimos en el ejercicio anterior,
y-within-frame
, tiene un problema. Si el valor de y es -1000, la función retorna -960. Dado que el valor de y del borde inferior del marco es -150, -960 queda afuera del marco. Tu tortuga va a quedar en un área invisible. Hagamos que la función sea realmente within-frame usandocond
.
-
Escribir una función
y-within-frame-cond
que recibe y (posición vertical) como argumento. -
Podés usar el ejemplo de
cond
del slide. -
La función debe retornar un valor de y entre -150 y 150.
;; uso de la función y-within-frame-cond
(y-within-frame-cond 200) ;=> -150
(y-within-frame-cond -200) ;=> 150
(y-within-frame-cond 0) ;=> 40
Las sentencias
if
no están limitadas a verificar sólo una cosa. Podés verificar múltiples condiciones usando lógica booleana. La Lógica booleana se refiere a combinar y cambiar el resultado de predicados usandoand
,or
, ynot
. {: ng-show="block81" .description}
Si nunca antes viste este concepto en programación, recordá que sigue el sentido común de cómo ves las cosas normalmente. Es esto y aquello verdadero? Sólo si ambos son verdaderos. Es esto o aquello verdadero? Sí, si cualquiera de ellos -- o ambos! -- lo son. Es esto no verdadero? Sí, si es falso. {: ng-show="block81" .description}
and
,or
, ynot
funcionan como otras funciones (no son exactamente funciones, pero funcionan como si lo fueran), entonces se usan con notación prefija, tal como vimos con los operadores aritméticos. {: ng-show="block91" .description}
x | y | (and x y) |
(or x y) |
(not x) |
(not y) |
---|---|---|---|---|---|
false | false | false | false | true | true |
true | false | false | true | false | true |
true | true | true | true | false | false |
false | true | false | true | true | false |
and
,or
, ynot
pueden ser combinados. Esto a veces puede ser difícil de leer. Veamos un ejemplo: {: ng-show="block101" .description}
(defn año-bisiesto?
"Cada cuatro años, excepto en años divisibles por 100,
pero sí para años divisibles por 400."
[year]
(and (zero? (mod year 4))
(or (zero? (mod year 400))
(not (zero? (mod year 100))))))
Aprendimos sobre
cond
,and
,or
, ynot
. Pensemos qué función podemos escribir combinando todos. Un ejemplo: {: ng-show="block110" .description}
(defn true-or-false?
"Dado op, retorna true o false"
[op]
(let [x true
y false]
(cond
(= op :and) (and x y)
:else false)))
(defn correct?
"Dados op y ans, retorna un mensaje indicando si ans fue correcta o no"
[op ans]
(if (= ans (true-or-false? op))
"Ganaste"
"Perdiste"))
La función
true-or-false?
en el slide anterior sólo "ve" la operación:and
. Agregá las operaciones:or
y:not
.
- Usá
core.clj
demyproject
e InstaREPL - Agregá
(= op :or)
y(= op :not)
en elcond
- Para
:not
, elegí x o y como argumento
;; uso de la función correct?
(correct? :and false) ;=> "Ganaste"
(correct? :or false) ;=> "Perdiste"
(correct? :not true) ;=> "Ganaste" (aunque podría ser "Perdiste")
{% comment %}
🌟 A link below is for a slide only. Go to README.md instead. 🌟
{% endcomment %}