Este exercício apresenta as condicionais: escolher entre dois ou mais caminhos de ação com base em um valor. Ele se baseia no Boolean que você conheceu em Infiltração da Annalyn e na aritmética de números inteiros de Conversão de Moedas.
Todas elas ficam em math (e em 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? (em math) é uma forma abreviada do teste comum 0 =:
ele consome o número e empilha se ele é zero ou não:
zero? ( n -- ? ) ! t when n is 0
between? (em math.order) testa se um valor cai dentro
de um intervalo inclusivo. É útil quando uma ação depende da faixa em que
um número cai:
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)
É comum vê-lo como um predicado de cond (dup 1 4 between?) para
escolher um bloco por intervalo em vez de por um único valor.
As palavras de comparação acima produzem Boolean; para agir sobre um
Boolean, você entrega à condicional uma ou mais quotations. Uma
quotation é um trecho de código envolvido por colchetes, [ ... ].
Escrevê-la empilha o código como um valor em vez de rodá-lo: uma palavra
como if então decide qual quotation rodar.
[ neg ] ! a quotation that negates the top of the stack
[ ] ! the empty quotation — does nothing
Um exercício posterior cobre as quotations por completo; por enquanto,
leia [ ... ] como "o código a executar para este bloco".
if, when, unless
if (em kernel) recebe um Boolean e duas quotations. Ele
executa a primeira quotation quando o Boolean é verdadeiro e a segunda
quando ele é falso:
if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;
when executa sua quotation apenas quando o Boolean é verdadeiro;
unless, apenas quando ele é falso:
when ( ? quot -- )
unless ( ? quot -- )
if*, when* e unless*
Três variantes de kernel tratam o Boolean como um valor que vale a pena
manter quando ele é verdadeiro, o que é útil quando uma palavra retorna
"a coisa, ou 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* é a forma de dois blocos. O bloco verdadeiro é chamado com o valor
ainda na pilha; o bloco falso é chamado sem ele:
42 [ ] [ "nothing" ] if* . ! prints 42
f [ ] [ "nothing" ] if* . ! prints "nothing"
unless* é a expressão idiomática canônica de "valor ou padrão". Se o
valor é verdadeiro, ele é deixado como está; se é f, o valor é
descartado e a quotation roda para empilhar um substituto:
"hello" [ "anonymous" ] unless* . ! => "hello"
f [ "anonymous" ] unless* . ! => "anonymous"
when* é a forma de um bloco de if*: ele executa sua quotation (com o
valor ainda na pilha) apenas quando o valor é verdadeiro, e simplesmente
descarta o valor quando ele é f. Recorra a ele para incorporar um
resultado do tipo "a coisa, ou f" a um valor acumulado sem se preocupar
em tratar o caso f:
0 41 [ + ] when* . ! => 41 (truthy: 41 added to the running total)
0 f [ + ] when* . ! => 0 (falsy: f dropped, total left untouched)
condQuando você tem várias ações alternativas entre as quais escolher, cond
(em combinators) é a escolha natural. Ele recebe um array
de pares { predicate body } e executa o corpo do primeiro predicado que
produz um valor verdadeiro:
USING: combinators ;
: classify ( n -- label )
{
{ [ dup 0 < ] [ drop "negative" ] }
{ [ dup 0 = ] [ drop "zero" ] }
[ drop "positive" ]
} cond ;
Alguns detalhes que vale a pena observar:
dup ... <test> é a expressão idiomática usual.drop na entrada e empilhando o resultado.Neste exercício você vai escrever código para analisar a produção de
uma linha de montagem em uma fábrica de carros. A velocidade da linha
de montagem pode variar de 0 (desligada) a 10 (máxima).
Na sua velocidade mais baixa diferente de zero (1), são produzidos 221
carros por hora. A produção aumenta linearmente com a velocidade, então na
velocidade 4 a linha produz 4 * 221 = 884 carros por hora. Porém,
velocidades mais altas aumentam a chance de que carros com defeito sejam
produzidos, e esses carros depois precisam ser descartados.
Você tem quatro tarefas. Cada uma recebe da pilha um único parâmetro inteiro: a velocidade da linha de montagem.
Defina production-status para retornar "stopped" quando a velocidade for 0
e "running" para qualquer outra velocidade:
0 production-status .
! => "stopped"
3 production-status .
! => "running"
Defina success-rate para retornar a probabilidade de um item ser
produzido sem erro:
0: 0.0
1 a 4: 1.0
5 a 8: 0.9
9: 0.8
10: 0.77
10 success-rate .
! => 0.77
Defina production-rate-per-hour para retornar a taxa de produção por
hora da linha de montagem, levando a taxa de sucesso em conta.
Você vai precisar definir base-speed primeiro, a constante 221.
6 production-rate-per-hour .
! => 1193.4
O valor retornado é um número de ponto flutuante.
Defina working-items-per-minute para retornar quantos carros funcionais
são produzidos por minuto. O resultado é um número inteiro: carros
parciais não são contados.
6 working-items-per-minute .
! => 19
Crie sua conta no Exercism para aprender e dominar Factor com 47 conceitos163 exercícios e mentoria humana de verdade, tudo de graça.