08 - függvény scope-ban

Nézzünk rá erre a kódra még egyszer:

1
2
3
4
def sum(i: Int, m: Int, s: Int): Int = {
  if( i > m ) s else sum(i+1, m, s+i)
}
def sum(n: Int, m: Int): Int = sum(n, m, 0)

Egy szépséghibája mindenképpen van: nem szeretnénk, hogy valaki csak úgy hívogassa a háromváltozós változatát a függvénynek, elvégre ez csak az ,,eredeti'' forciklus helyett szerepel. A legjobb az lenne, ha nem is lehetne meghívni.

Scalában van lehetőségünk a függvényeinket egy másik függvény scope-ján belül deklarálni:

1
2
3
4
5
6
7
8
def sum(n: Int, m: Int): Int = { 

  def sum(i: Int, m: Int, s: Int): Int = {
    if( i > m ) s else sum(i+1, m, s+i)
  }

  sum(n, m, 0)
}

Tehát: ,,kintről'' csak a sum(n: Int, m: Int) függvény látszik, őt meghívjuk, ekkor ezen a függvényblokkon belül fogjuk látni a háromváltozós változatot, ott van defelve, és ezután a sum(n,m,0) az eredeti hívásunk. Gyakorlatilag a kétváltozós függvényünkben deklarálunk egy háromváltozóst, aztán az értéket úgy kapjuk, hogy ezt a háromváltozóst értékeljük ki megfelelő argumentumokon.

Ha jobban megfigyeljük, a belső, háromváltozós függvény most már ,,feleslegesen'' passzolja magának az m értéket: azt nem változtatja meg és eleve láthatja is, hiszen a sum kétváltozós függvényen belül, ahol deklaráljuk a belső sumot, ott már látszik a kétváltozós függvény két argumentuma! Ezeket a bent deklarált függvényekben is elérjük, tehát tudunk rövidíteni a kódon:

1
2
3
4
5
6
7
8
def sum(n: Int, m: Int) = { 

  def sum(i: Int, s: Int): Int = {
    if( i > m ) s else sum(i+1, s+i)
  }

  sum(n, 0)
}

A másik jó hír, hogy így már a Scala fordító is tudja inferni, hogy a sum kétváltozós függvény az egy Intet ad vissza, ezért azt is törölhetjük a fejlécéből. (Míg két ugyanolyan nevű függvényünk volt egymás mellett, és az egyik rekurzív volt, ez megzavarta annyira, hogy a másiknak a típusát se tudja levezetni.)

Kérdések, feladatok

  • Alakítsuk át az eddigi tailrec függvényeinket (faktoriális, 1-től n-ig println) így, elrejtve a belső tail rekurzív implementációt. Csökkentsük a belső tailrec függvény paramétereinek a számát is, amennyire lehet.

Utolsó frissítés: 2020-12-23 19:43:13