Ez a feladat az elágazásokat mutatja be: hogyan válasszunk kettő vagy több cselekvési irány közül egy érték alapján. Arra a Boolean-okra épül, amelyekkel az Annalyn's Infiltration feladatban találkoztál, és a Currency Conversion egész számokkal végzett aritmetikájára.
Ezek mind a math-ban találhatók (a = pedig a kernel-ben):
= ( 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)
A zero? (a math-ban) a gyakori 0 = vizsgálat rövidítése: elfogyasztja a számot, és a veremre teszi, hogy nulla volt-e:
zero? ( n -- ? ) ! t when n is 0
A between? (a math.order-ben) azt vizsgálja, hogy egy érték egy zárt intervallumba esik-e. Akkor jön jól, amikor egy művelet attól függ, melyik sávba esik egy szám:
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)
Gyakran fogod látni cond predikátumként, például dup 1 4 between?, hogy egy ágat értéktartomány, ne pedig egyetlen érték alapján válassz ki.
A fenti összehasonlító szavak Boolean-okat adnak vissza; hogy egy Boolean alapján cselekedj, adj át az elágazásnak egy vagy több quotationt. A quotation egy szögletes zárójelbe zárt kódrészlet: [ ... ]. Ha leírod, a kód értékként kerül a veremre ahelyett, hogy lefutna. Egy if-hez hasonló szó aztán eldönti, melyik quotation fusson le.
[ neg ] ! a quotation that negates the top of the stack
[ ] ! the empty quotation — does nothing
Egy későbbi feladat részletesen foglalkozik a quotationokkal; most egyelőre olvasd úgy a [ ... ]-t, mint „az ebben az ágban lefutó kód”.
if, when, unless
Az if (a kernel-ben) egy Boolean-t és két quotationt vár. Az első quotationt akkor futtatja le, amikor a Boolean igaz értékű, a másodikat pedig akkor, amikor hamis értékű:
if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;
A when csak akkor futtatja le a quotationt, amikor a Boolean igaz értékű; az unless pedig csak akkor, amikor hamis értékű:
when ( ? quot -- )
unless ( ? quot -- )
if*, when* és unless*
A kernel három változata úgy kezeli a Boolean-t, mint egy értéket, amelyet érdemes megtartani, amikor igaz értékű. Ez akkor hasznos, amikor egy szó „a dolgot vagy f-et” ad vissza:
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
Az if* a kétágú forma. Az igaz ág úgy hívódik meg, hogy az érték még a vermen van; a hamis ág pedig anélkül hívódik meg:
42 [ ] [ "nothing" ] if* . ! prints 42
f [ ] [ "nothing" ] if* . ! prints "nothing"
Az unless* a klasszikus „érték vagy alapérték” idióma. Ha az érték igaz értékű, érintetlenül marad; ha f, az érték lekerül a veremről, és a quotation fut le, hogy egy helyettesítő értéket tegyen a helyére:
"hello" [ "anonymous" ] unless* . ! => "hello"
f [ "anonymous" ] unless* . ! => "anonymous"
A when* az if* egyágú formája: csak akkor futtatja le a quotationt (úgy, hogy az érték még a vermen van), amikor az érték igaz értékű, és egyszerűen lekerül a veremről, amikor f. Akkor nyúlj hozzá, amikor egy „a dolog vagy f” típusú eredményt szeretnél az aktuális értékbe beépíteni anélkül, hogy az f esettel külön kellene foglalkoznod:
0 41 [ + ] when* . ! => 41 (truthy: 41 added to the running total)
0 f [ + ] when* . ! => 0 (falsy: f dropped, total left untouched)
condAmikor több lehetséges cselekvés közül kell választanod, a cond (a combinators-ban) a kézenfekvő választás. Egy { predicate body } párokból álló tömböt vár, és annak az első predikátumnak a törzsét futtatja le, amely igaz értéket ad:
USING: combinators ;
: classify ( n -- label )
{
{ [ dup 0 < ] [ drop "negative" ] }
{ [ dup 0 = ] [ drop "zero" ] }
[ drop "positive" ]
} cond ;
Néhány részlet, amit érdemes megjegyezni:
dup ... <test>.drop-pal eltávolítja a bemenetet, és az eredményt a veremre teszi.Ebben a feladatban olyan kódot írsz, amely egy autógyár szerelősorának termelését elemzi. A szerelősor sebessége 0 (kikapcsolva) és 10 (maximum) között mozoghat.
A legkisebb nullától különböző sebességén (1) óránként 221 autó készül. A termelés lineárisan nő a sebességgel, így 4-es sebességnél a sor óránként 4 * 221 = 884 autót gyárt. A nagyobb sebesség viszont megnöveli annak valószínűségét, hogy hibás autók készülnek, amelyeket aztán ki kell selejtezni.
Négy részfeladatod van. Mindegyik egyetlen egész szám paramétert vesz le a veremből: a szerelősor sebességét.
Definiáld a production-status szót úgy, hogy "stopped" értéket adjon vissza, ha a sebesség 0, és "running" értéket minden más sebesség esetén:
0 production-status .
! => "stopped"
3 production-status .
! => "running"
Definiáld a success-rate szót úgy, hogy egy elem hibamentes legyártásának valószínűségét adja vissza:
0: 0.0
1 to 4: 1.0
5 to 8: 0.9
9: 0.8
10: 0.77
10 success-rate .
! => 0.77
Definiáld a production-rate-per-hour szót úgy, hogy a szerelősor óránkénti termelési rátáját adja vissza, figyelembe véve a sikerességi arányt.
Először a base-speed szót kell definiálnod, a 221 konstanst.
6 production-rate-per-hour .
! => 1193.4
A visszaadott érték lebegőpontos szám.
Definiáld a working-items-per-minute szót úgy, hogy visszaadja, hány működő autó készül percenként. Az eredmény egész szám, a töredék autókat nem számoljuk.
6 working-items-per-minute .
! => 19
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Factor nyelvet 47 fogalom163 feladat segítségével, valódi emberi mentorálással, mindez ingyen.