Kurzusok
/
Common Lisp
Common Lisp
/
Feladatok
/
Lilly lasagnamaradéka
Lilly lasagnamaradéka

Lilly lasagnamaradéka

Tanulófeladat

Bevezetés

Lambda lista

A Common Lispben egy függvény argumentumlistáját lambda listának nevezik. A lambda listában különböző típusú argumentumok lehetnek. Ezeket a különböző típusokat lambda listakulcsszavakkal jelölik, amelyek mindegyike &-nel kezdődik. A leggyakrabban használt típusok az opcionális, a kulcsszó- és a maradék argumentumtípusok. Egy adott lambda listakulcsszó után a lambda listában szereplő minden paraméter abból a típusból lesz. Egy lambda listakulcsszó csak egyszer használható egy lambda listában.

A lambda listákat más szerkezetekben is használják, amelyekről később lesz szó, például a destrukturálásnál és a makróknál.

Opcionális paraméterek

A Common Lispben egy függvénynek lehetnek opcionális argumentumai. Ezeket a lambda listában a &optional lambda listakulcsszó jelöli. Ha egy paramétert nem adunk meg, akkor a nil értéket kapja. Ha több opcionális paraméter van, akkor sorrendben kapják meg az értéküket. Az opcionális paraméterekhez alapértelmezett érték is megadható. Végül minden opcionális paraméterhez megadható egy szimbólum, amely igaz vagy hamis értéket kap attól függően, hogy a függvény hívója megadta-e az adott paramétert (ezt nevezik „supplied-p paraméternek”).

(defun optional-parameters (&optional x (y 'default) (z nil z-supplied-p))
  (list x y (if z-supplied-p (list :z-was-supplied z)
                             (list :z-was-not-supplied z))))

(optional-parameters)          ; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(optional-parameters 5 nil 10) ; => (5 NIL (:Z-WAS-SUPPLIED 10))

Kulcsszó paraméterek

A Common Lispben egy függvénynek lehetnek nevesített paraméterei (ezeket „kulcsszó paramétereknek” nevezik). Ezeket a lambda listában a &key lambda listakulcsszó jelöli. A kulcsszó paraméterek nem kötelező paraméterek. Az opcionális paraméterekhez hasonlóan kaphatnak alapértelmezett értéket, és szimbólumot ahhoz, hogy meg vannak-e adva vagy sem.

Amikor egy függvényt kulcsszó paraméterekkel hívunk meg, a paraméter neve kulcsszóként a paraméter értéke elé kerül. A kulcsszó paramétereket a függvény hívója tetszőleges sorrendben megadhatja.

(defun keyword-parameters (&key x (y 'default) (z nil z-supplied-p))
  (list x y (if z-supplied-p (list :z-was-supplied z)
                             (list :z-was-not-supplied z))))

(keyword-parameters)            ; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :y 5)       ; => (NIL 5 (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :z 10 :x 5) ; => (5 DEFAULT (:Z-WAS-SUPPLIED 10))

Ügyelni kell arra, amikor az opcionális és a kulcsszó paramétereket kombináljuk, mert a kulcsszó nevét és argumentumát az opcionális paraméterek elnyelhetik:

(defun could-be-confusing (&optional x y &key z) (list x y z))
(could-be-confusing :z 'huh?) ; => (:Z HUH? NIL)

Maradék paraméterek

A Common Lispben egy függvénynek lehet olyan paramétere, amely az argumentumok „maradékát” tartalmazza, miután minden kötelező vagy opcionális paraméter feldolgozásra került. Ezt a paramétert a &rest lambda listakulcsszó jelöli. Ha a függvény összes argumentumát más típusú paraméterek használják fel, akkor a maradék paraméter egy üres listát kap. Ha maradnak fel nem használt argumentumok, akkor a maradék paraméter ezek listáját kapja.

(defun rest-of-it (req &optional opt &rest rest) (list req opt rest))
(rest-of-it 1)         ; => (1 NIL NIL)
(rest-of-it 1 2)       ; => (1 2 NIL)
(rest-of-it 1 2 3)     ; => (1 2 (3))
(rest-of-it 1 2 3 4 5) ; => (1 2 (3 4 5))

Utasítások

Lilly, a Lisp-űrlény a segítségeddel bizony rengeteg lasagnét készített. Szeretné megköszönni neked azzal, hogy ad neked a maradékból. De előbb van néhány visszajelzése az egyik függvényről, amelyben segítettél neki.

Ebben a feladatban még néhány függvényt fogsz írni, hogy segíts Lillynek a lasagnafőzésben, és abban is, hogy megossza veled a maradékot.

Hat részfeladatod van: három a meglévő lasagnafőző függvények fejlesztéséről, és három a maradék szétosztásáról.

1. Tedd könnyebben használhatóvá a preparation-time-in-minutes függvényt

Lilly szerint a preparation-time-in-minutes használata kissé kényelmetlen volt, mert a függvények használata előtt meg kellett számolnia az összes réteget. Lilly azon tűnődik, meg tudnád-e csinálni a függvény egy olyan változatát, amely argumentumként fogadja a rétegeket (akárhányat), majd a rétegek száma alapján kiszámítja az előkészítési időt? Emlékeztetőül: egyetlen réteg előkészítése 19 percet vesz igénybe.

(preparation-time 'sauce 'cheese 'right-handed-macaroni 'cheese 'sauce
                  'left-handed-macaroni 'sauce 'sauce 'cheese 'cheese)
                  ;; => 190 (because there are 10 layers.)

2. Tedd lehetővé a várt sütési idő módosítását

Bár Lilly szülőegységei mindig 337 percig sütötték a lasagnéjukat, Lilly elismeri, hogy más Lisp-űrlények szeretnek hosszabb vagy rövidebb ideig sütni.

Ezért jó lenne, ha a remaining-minutes-in-oven nem a expected-minutes-in-oven értékét használná, hanem egy opcionális paramétert fogadna, amely meghatározza, hogy az idő hosszabb, nagyon hosszú, rövidebb vagy nagyon rövid legyen. A hosszabb vagy rövidebb 100 hozzáadását vagy levonását jelenti a 337-es alapértékhez képest. A nagyon hosszú vagy nagyon rövid 200 hozzáadását vagy levonását jelenti. Ha nincs megadva paraméter, vagy az argumentum 'normal', akkor a 337-es alapértéket kell visszaadni.

(remaining-minutes-in-oven)             ;; => 337
(remaining-minutes-in-oven :normal)     ;; => 337
(remaining-minutes-in-oven :shorter)    ;; => 237
(remaining-minutes-in-oven :very-short) ;; => 137
(remaining-minutes-in-oven :longer)     ;; => 437
(remaining-minutes-in-oven :very-long)  ;; => 537

3. Lilly eszébe jut egy másik kedvelt főzési stílus

Alighogy befejezted ezt a módosítást, Lillynek eszébe jut, hogy vannak olyan Lisp-űrlények, akik nagyon rövid főzési időt szeretnek. Gyakorlatilag nyersen szeretik. Ezért most a függvénynek 0-t kell visszaadnia, ha NIL volt az argumentum, valamint ugyanazokat az értékeket, mint az előző részfeladatban.

(remaining-minutes-in-oven)     ;; => 337
(remaining-minutes-in-oven nil) ;; => 0

4. A maradék szétosztása

Most, hogy segítettél fejleszteni a lasagnafőző függvényeket, rengeteg lasagne van! Lilly szeretné meghálálni a segítségedet azzal, hogy megosztja veled a maradékot. Olyan függvényt kell írnod, amely három paramétert fogad: a maradék teljes mennyiségét, a Lilly szekrényeiben talált maradéktároló dobozok számát, és a neked talált dobozok számát. Mivel a maradéktároló dobozok keresése különböző ideig tarthat, és a maradék pontos mennyisége is kiderülhet, miközben te és Lilly épp a szekrényeiteket kutatjátok, mindketten abban állapodtok meg, hogy a függvény bármilyen sorrendben fogadhatja az argumentumokat, így ahogy minden szám megvan, leírhatod. Amikor mindhárom szám megvan, csak be kell zárnod a zárójelet a függvényhíváson, és ki kell értékelned.

A függvénynek a megmaradó maradék mennyiségét kell visszaadnia, vagyis a maradék tömegének és a te és Lilly által talált dobozok összes számának a különbségét.

(split-leftovers :weight 20 :human 10 :alien 5) ;; => 5
(split-leftovers :weight 20 :alien 10 :human 2) ;; => 8
(split-leftovers :alien 12 :weight 20 :human 4) ;; => 4

5. Feltételezések

Miután néhányszor oda-vissza sétáltatok a saját szekrényeitekhez, mindketten abban is megállapodtok, hogy remek lenne, ha a függvény egyszerűen feltételezné, hogy neked vagy Lillynek... mondjuk 10 dobozod van, ha nincs megadva.

(split-leftovers :weight 20 :human 5) ;; => 5
(split-leftovers :weight 20 :alien 5) ;; => 5
(split-leftovers :weight 20)          ;; => 0

6. A maradék szokásos mennyisége

Még jobb lenne, ha a függvény azt feltételezné, hogy elég maradék van ahhoz, hogy elférjen a dobozokban. Így ha a tömeg nincs megadva, a függvénynek :just-split-it értéket kell visszaadnia. Azonban ha a tömeg meg van adva, és az nil, akkor :looks-like-someone-was-hungry értéket kell visszaadnia.

(split-leftovers :human 5 :alien 5) ;; => :JUST-SPLIT-IT
(split-leftovers :weight NIL :human 5 :alien 5) ;; => :LOOKS-LIKE-SOMEONE-WAS-HUNGRY
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Common Lisp Exercism

Készen állsz elkezdeni a(z) Lilly lasagnamaradéka feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Common Lisp nyelvet 27 fogalom92 feladat segítségével, valódi emberi mentorálással, mindez ingyen.