Este ejercicio presenta los condicionales: elegir entre dos o más alternativas según un valor. Se apoya en los Boolean que viste en Infiltración de Annalyn y en la aritmética con enteros de Conversión de monedas.
Todas estas viven en math (y en kernel para =):
= ( x y -- ? ) ! equal
< ( x y -- ? ) ! less than
<= ( x y -- ? ) ! less than or equal
> ( x y -- ? ) ! greater than
>= ( x y -- ? ) ! greater than or equal
3 3 = . ! => t
2 3 < . ! => t
3 3 <= . ! => t
3 4 = not . ! => t (inequality: combine = with not)
zero? (en math) es una forma abreviada de la prueba habitual 0 =: consume el número y apila si era cero:
zero? ( n -- ? ) ! t when n is 0
between? (en math.order) comprueba si un valor cae dentro de un rango inclusivo. Es útil cuando una acción depende de la franja en la que cae un número:
between? ( x lo hi -- ? ) ! lo <= x <= hi (inclusive)
5 1 10 between? . ! => t
0 1 10 between? . ! => f
10 1 10 between? . ! => t (inclusive at both ends)
A menudo lo verás como predicado de cond, dup 1 4 between?, para elegir una rama por rango en lugar de por un único valor.
Las palabras de comparación anteriores producen Boolean; para actuar sobre un Boolean le entregas al condicional una o más quotations. Una quotation es un fragmento de código entre corchetes, [ ... ]. Escribirla apila el código en la pila como un valor en lugar de ejecutarlo, y luego una palabra como if decide qué quotation ejecutar.
[ neg ] ! a quotation that negates the top of the stack
[ ] ! the empty quotation — does nothing
Un ejercicio posterior cubre las quotations en detalle; por ahora, lee [ ... ] como «el código que se ejecuta para esta rama».
if, when, unless
if (en kernel) recibe un Boolean y dos quotations. Ejecuta la primera quotation cuando el Boolean es verdadero y la segunda cuando es falso:
if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;
when ejecuta su quotation solo cuando el Boolean es verdadero; unless, solo cuando es falso:
when ( ? quot -- )
unless ( ? quot -- )
if*, when* y unless*
Tres variantes de kernel tratan el Boolean como un valor que vale la pena conservar cuando es verdadero. Son útiles cuando una palabra devuelve «el valor, o f»:
if* ( ? true false -- ) ! truthy: true is called WITH ? on stack
when* ( ? true -- ) ! truthy: true is called WITH ? on stack
unless* ( ? false -- ) ! falsy: false runs and pushes a default
if* es la forma de dos ramas. La rama verdadera se llama con el valor todavía en la pila; la rama falsa se llama sin él:
42 [ ] [ "nothing" ] if* . ! prints 42
f [ ] [ "nothing" ] if* . ! prints "nothing"
unless* es la expresión canónica de «el valor o un valor por defecto». Si el valor es verdadero, se deja intacto; si es f, el valor se descarta y la quotation se ejecuta para apilar un sustituto:
"hello" [ "anonymous" ] unless* . ! => "hello"
f [ "anonymous" ] unless* . ! => "anonymous"
when* es la forma de una sola rama de if*: ejecuta su quotation, con el valor todavía en la pila, solo cuando el valor es verdadero, y simplemente descarta el valor cuando es f. Úsala para incorporar un resultado del tipo «el valor, o f» a un valor acumulado sin molestarte en manejar el caso f:
0 41 [ + ] when* . ! => 41 (truthy: 41 added to the running total)
0 f [ + ] when* . ! => 0 (falsy: f dropped, total left untouched)
condCuando tienes varias acciones alternativas entre las que elegir, cond (en combinators) es la opción natural. Recibe un array de pares { predicate body } y ejecuta el cuerpo del primer predicado que produzca un valor verdadero:
USING: combinators ;
: classify ( n -- label )
{
{ [ dup 0 < ] [ drop "negative" ] }
{ [ dup 0 = ] [ drop "zero" ] }
[ drop "positive" ]
} cond ;
Algunos detalles que vale la pena tener en cuenta:
dup ... <test> es la expresión habitual.drop y apilando el resultado.En este ejercicio vas a escribir código para analizar la producción de una línea de ensamblaje en una fábrica de autos. La velocidad de la línea de ensamblaje puede ir de 0 (apagada) a 10 (máxima).
A su velocidad mínima distinta de cero (1), se producen 221 autos cada hora. La producción aumenta de forma lineal con la velocidad, así que a velocidad 4 la línea produce 4 * 221 = 884 autos por hora. Sin embargo, las velocidades más altas aumentan la probabilidad de que se produzcan autos defectuosos, que después hay que desechar.
Tienes cuatro tareas. Cada una toma de la pila un único parámetro entero, la velocidad de la línea de ensamblaje.
Define production-status para que devuelva "stopped" cuando la velocidad sea 0 y "running" para cualquier otra velocidad:
0 production-status .
! => "stopped"
3 production-status .
! => "running"
Define success-rate para que devuelva la probabilidad de que una unidad se produzca sin errores:
0: 0.0
1 a 4: 1.0
5 a 8: 0.9
9: 0.8
10: 0.77
10 success-rate .
! => 0.77
Define production-rate-per-hour para que devuelva la tasa de producción por hora de la línea de ensamblaje, teniendo en cuenta la tasa de éxito.
Primero tendrás que definir base-speed, la constante 221.
6 production-rate-per-hour .
! => 1193.4
El valor que se devuelve es de punto flotante.
Define working-items-per-minute para que devuelva cuántos autos funcionales se producen por minuto. El resultado es un número entero: no se cuentan los autos incompletos.
6 working-items-per-minute .
! => 19
Regístrate en Exercism para aprender y dominar Factor con 47 conceptos163 ejercicios y mentoría humana real, todo gratis.