Kurzusok
/
Factor
Factor
/
Feladatok
/
A lasagne csillaga
A lasagne csillaga

A lasagne csillaga

Tanulófeladat

Bevezetés

A veremmel való zsonglőrködés rövid szavaknál rendben van. Ha viszont egy szónak több bemenete van, és ezekre név szerint kell hivatkoznod, a Factor lokálisokat kínál: névvel ellátott kötéseket, amelyeket a :: (szódefiníciókhoz) vagy a [| | ] (beágyazott lambdákhoz) vezet be.

:: ( inputs -- outputs )

Cseréld le a :-t ::-ra, és a bemeneti nevekből lokális változók lesznek a törzsben:

USING: locals ;

:: hypotenuse ( a b -- c )
    a a *
    b b *
    + sqrt ;

Hasonlítsd össze a veremrendezgetős változattal:

! DOCTEST: SKIP   (shown for comparison — would re-define hypotenuse)
: hypotenuse ( a b -- c )
    [ sq ] bi@ + sqrt ;

Mindkettő helyes. A lokálisok akkor a leghasznosabbak, ha egy bemenetre többször hivatkozol, vagy ha a műveletek sorrendje nem esik egybe természetesen a verem sorrendjével.

Köztes értékek kötése a :> segítségével

A ::-tal létrehozott törzsben (vagy egy beágyazott [| ... |] lambdában) a :> levesz egy értéket az adatveremről, és egy friss lokálishoz köti:

value :> name      ! immutable binding
value :> name!     ! mutable binding (name! is its setter)

A változtathatatlan forma a gyakoribb: ezzel nevezhetsz el egy köztes értéket, hogy a törzs fentről lefelé olvasható legyen:

USING: locals math ;

:: average-3 ( x y z -- avg )
    x y + z + :> sum
    sum 3 / ;

A ! végződés módosíthatóként deklarálja a lokálist; a törzs későbbi részében a value name! (kettőspont és :> nélkül) új értéket ad neki:

USING: kernel locals math math.order ;

:: clamped ( x lo hi -- y )
    x :> v!
    v lo < [ lo v! ] when
    v hi > [ hi v! ] when
    v ;

A módosítható lokálisok azokban az iterációs szavakban hasznosak igazán, amelyekkel a későbbi feladatokban találkozol (pl. while).

[let - scope bárhonnan

A :> csak lexikális scope-on belül működik, amit a :: és a [| ... |] automatikusan létrehoz. Ha egy sima :-os szóból vagy a listenerből szeretnél lokálisokat bevezetni, csomagold a kódot [let ... ]-be:

[let code :> name code :> name ... body ]

Minden :> name az előző kifejezés verem tetején lévő értékét köti; a kötések a forma további részében is láthatók.

USING: locals math ;

[let 3 :> x 4 :> y x x * y y * + ] .   ! => 25

A [let a híd a veremstílusú :-os definíciók és a névvel ellátott kötések között. Kényelmes, amikor egy szónak csak egy szelete profitál a lokálisokból.

Lambdák - [| inputs | body ]

Egy quotation belsejében a [| inputs | body ] olyan lokálisokat vezet be, amelyekre a törzs név szerint hivatkozhat. Ez különösen hasznos magasabb rendű szavaknál, például az assoc-map-nél, ahol a quotation a key és a value értéket is megkapja:

USING: assocs locals ;

H{ { "a" 1 } { "b" 2 } }
[| key value | key value neg ] assoc-map .
! => H{ { "a" -1 } { "b" -2 } }

Ugyanez a forma működik a map-index-nél is (a [sequences][sequences] szókészletben), amelynek a quotationje az elemet és annak indexét is megkapja. A nevek világossá teszik, melyik operandus milyen szerepet játszik:

USING: locals sequences ;

! Divide each element by its 1-based position:
{ 10 80 270 } [| elt i | elt i 1 + / ] map-index .
! => { 10 40 90 }

A lambda veremhatását a bemeneti lista és a törzs által előállított értékek határozzák meg.

Mikor használj lokálisokat

Akkor nyúlj a lokálisokhoz, ha:

  • Ugyanazt a bemenetet több helyen is használod.
  • A műveletek természetes sorrendje nem egyezik a verem sorrendjével, és a javításukra szolgáló dup/swap/rot nehezen olvasható.
  • Egy magasabb rendű szónak átadott beágyazott lambdában vagy, amely egyszerre több értéket ad át neked (mint az assoc-map-nél).

Ha a törzs tiszta, lineáris folyam, a sima :-os definíciók rövidebbek és legalább olyan olvashatók maradnak.

assoc-map - egyszerre egy bejegyzés

Az assoc-map (a assocs szókészletben) egy quotationt futtat le egy asszociatív gyűjtemény minden egyes bejegyzésén:

assoc-map ( assoc quot: ( key value -- newkey newvalue ) -- newassoc )

A quotation megírásának legtisztább módja egy lokálisokat használó lambda.

cond újra

Amikor f vagy egy számérték alapján kell elágaznod, a cond pont a megfelelő forma. Nem kell case, mert nincs egyetlen érték, amihez hasonlíthatnál.

Utasítások

Megint a konyhában vagy, és tovább finomítod a lasagne receptjét a Leah ínycsiklandó lasagnéja feladatból. Az itteni részfeladatokban egyszerre több bemenettel kell zsonglőrködnöd, és pont ilyenkor jönnek jól a locals, a Factor névvel ellátott kötései.

1. Határozd meg a főzés állapotát

Definiáld a cooking-status szót úgy, hogy kivegyen egy időzítőértéket a veremről, és egy állapotot leíró stringet adjon vissza.

  • 0 → "Lasagna is done."
  • f (az időzítőt sosem állítottad be) → "You forgot to set the timer."
  • bármely más szám → "Not done, please wait."
12 cooking-status .   ! => "Not done, please wait."
0 cooking-status .    ! => "Lasagna is done."
f cooking-status .    ! => "You forgot to set the timer."

2. Becsüld meg az előkészítési időt

Definiáld a preparation-time szót úgy, hogy kapjon egy tömböt a rétegek neveivel és a rétegenkénti átlagos percszámot, majd adja vissza a teljes előkészítési időt.

{ "sauce" "noodles" "sauce" "meat" "mozzarella" "noodles" } 3 preparation-time .
! => 18

3. Számítsd ki a szükséges tésztát és szószt

Definiáld a quantities szót úgy, hogy kapjon egy tömböt a rétegek neveivel, és két értéket adjon vissza: a szükséges tészta grammját (tésztarétegenként 50 g) és a szükséges szósz literjét (szószrétegenként 1/5 liter).

{ "sauce" "noodles" "sauce" "meat" "mozzarella" "noodles" } quantities .s
! => 100
! => 2/5

4. Add hozzá a titkos összetevőt

A barátod küld egy listát az összetevőkről, és a legutolsó elem a titka. Definiáld az add-secret-ingredient szót úgy, hogy kapja meg az ő listáját és a tiédet, majd adja vissza a te listádat a titkos összetevővel a végén.

{ "noodles" "sauce" "mozzarella" "kampot pepper" }
{ "noodles" "meat" "sauce" "mozzarella" }
add-secret-ingredient .
! => { "noodles" "meat" "sauce" "mozzarella" "kampot pepper" }

5. Méretezd át a receptet

A szakácskönyv receptje két adagra elég. Definiáld a scale-recipe szót úgy, hogy kapjon egy receptet (egy hashtable-t, amely az összetevő nevéhez rendeli a mennyiséget) és a cél adagszámot, majd adjon vissza egy új, megfelelően átméretezett receptet.

H{ { "noodles" 200 } { "sauce" 1/2 } { "mozzarella" 1 } { "meat" 100 } }
4 scale-recipe .
! => H{ { "noodles" 400 } { "sauce" 1 } { "mozzarella" 2 } { "meat" 200 } }
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Factor Exercism

Készen állsz elkezdeni a(z) A lasagne csillaga feladatot?

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.