Kihagyás

04 - false and loop

Láttuk, hogy függvényeket a def kulcsszóval vezetünk be, nézzünk erre pár példát.

Az előadás alapján egy függvényt, ami összead két intet, így írnánk meg:

1
2
3
def osszeAd(x: Int, y: Int): Int = {
  x+y
}

Ezzel kapcsolatban amit érdemes észben tartanunk:

  • Ha a függvénytörzsben lévő kifejezés típusát ki tudja következtetni a Scala és az nekünk megfelel, nem kell kiírnunk a függvény visszatérési értékét.
  • Ha a függvénytörzsben egyetlen kifejezés szerepel, akkor nem kell kitegyük a kapcsos zárójeleket.
  • Ha a függvény nem vár egyetlen argumentumot sem, akkor nem kell kitegyük a () jelet a függvény neve mögé (és ekkor meghívni is enélkül tudjuk.)

Próbáljuk is ki:

1
2
3
def osszeAd(x: Int, y: Int) = x+y

println( osszead(2,3) ) //prints 5
Az osszeAd függvény kimeneti típusát tehát a fordító Intre inferreli nekünk, ezt az idea szürkével jelzi is:

inferred Int

Tipikusan a rekurzív függvények azok, melyeknek a Scala nem fog tudni automatikusan típust inferrelni.

A paraméter nélküli függvényekkel kapcsolatban a Scala style guide (note: érdemes nézegetni a Scala coding konvenciókat ezen az oldalon, sokkal olvashatóbb kódot tud írni az ember, ha betartja azokat az ajánlásokat, melyeket többé-kevésbé mindenki betart, és Scalában a kód jó olvashatósága must have) azt írja, hogy

  • ha a metódus, melynek nincs paramétere, nem rendelkezik mellékhatással és tényleg csak egy értéket ad vissza, akkor hagyjuk el a nyitó-csukójeleket,
  • de ha van mellékhatása (pl a println() ilyen: visszaadja a () értéket, ami az egyetlen Unit típusú érték, de közben üt egy újsort a konzolra ,,mellékhatásként''), akkor tegyük ki a zárójeleket!

Kérdések, feladatok

Írjunk egy loop függvényt, ami típusát tekintve Booleant ad vissza, de mindig végtelen ciklusba esik.

válasz mutatása
1
def loop: Boolean = loop

Írjunk egy and függvényt, ami két Boolean kifejezést vár, és pontosan akkor ad vissza truet, ha mindkettő értéke true. Legyen gyorsított kiértékelés: ha az első argumentum értéke false, akkor a másodikat ki se értékelje.

1
def and(x: Boolean, y: =>Boolean) = if(x) y else false 
válasz mutatása

Az előző kérdés minta megoldásának miért lehet a második paraméter típusa olyan, amilyen?

Az `x` argumentum értékét mindenképpen használjuk egyszer, ezért ez call-by-value lett; az `y` argumentum értékét viszont vagy egyszer, vagy nullaszor, ez ezért lett call-by-name. válasz mutatása

Tudsz olyan hívást mondani, ahol az and függvény másképp viselkedik, ha call-by-name vagy call-by-value kezeljük a paramétereket?

válasz mutatása `and(false,loop)` például végtelen ciklusba esik, ha érték szerint adjuk át a második paramétert. Ha név szerint, akkor nem: működik a gyorsított kiértékelés a call-by-name konvenció miatt.

Implementáld le az or, not, implies, iff, xor logikai műveleteket is, ott használva gyorsított kiértékelést, ahol csak lehet.

1
2
3
4
5
6
7
8
9
def or(x: Boolean, y: =>Boolean) = if(x) true else y

def not(x: Boolean) = if(x) false else true

def implies(x: Boolean, y: =>Boolean) = if(x) y else true

def iff(x: Boolean, y:Boolean) = if(x) y else not(y)

def xor(x: Boolean, y:Boolean) = if(x) not(y) else y
Természetesen ezeket csak gyakorlás céljából írtuk meg: `Boolean`ok közt használjuk rendre a `&&`, `||`, `!` operátorokat. Válasz mutatása

Utolsó frissítés: 2021-02-07 23:06:47