/ / Sú tieto dve definície funkcií rovnocenné? - scala

Sú tieto dve funkčné definície ekvivalentné? - scala

Práve som sledoval prednášku 2.2 Funkcie vyššieho rádu (pre Princípy funkčného programovania v Scale). Tam je funkcia súčtu definovaná takto:

def sum(f: Int => Int, a: Int, b: Int) { ... }

Neskôr je rovnaká funkcia definovaná takto:

def sum(f: Int => Int)(a: Int, b: Int) { ... }

Zdá sa, že sú rovnocenné, ale nie je uvedené vysvetlenie, prečo zvoliť radšej vôbec.

odpovede:

2 pre odpoveď č. 1

Druhá definícia deklaruje metódu s dvoma zoznamami argumentov. Ignorovanie implicitných údajov sa potom zvyčajne používa na povolenie kari funkčné aplikácie.Základnou myšlienkou je, že môžete viazať niektoré parametre funkcie, ktoré poskytujú inú funkciu s menším počtom argumentov, a to tie, ktoré ešte nie sú viazané. Tu je jednoduchý príklad učebnice:

def add(xs: List[Int])(y: Int) =
xs.map(_ + y)

// Bind first argument and store resulting function in f
val f = add(List(2,3,5,7,11))_

println(f(0))  // List(2, 3, 5, 7, 11)
println(f(10)) // List(12, 13, 15, 17, 21)

// Bind first argument and store resulting function in g
val g = add(List(0,1,0,1,0,1))_

println(g(1))  // List(1, 2, 1, 2, 1, 2)
println(g(-1)) // List(-1, 0, -1, 0, -1, 0)

// Regular invocation
println(add(List(1,2,3))(4)) // List(5, 6, 7)

Nájdete veľa článkov o kari, napríklad o tom, ako používať kari v Scale, alebo že existujú viac spôsobov kari v Scale.

Pokiaľ ide o dôvod, prečo si vybrať jednu z týchto možností:V Haskelli by ste si v zásade vždy vybrali verziu s curryovou verziou pred verziou bez curries, pretože tá vám dáva výhodu možnosti čiastočného viazania parametrov a keďže pri použití verzií curried neexistuje žiadny „syntaxový trest“ alebo runtime trest. Pretože to pre Scalu neplatí (ako je zrejmé z vyššie uvedeného úryvku kódu, pokiaľ ide o syntax), možno budete chcieť uprednostniť nevyučený štýl, iba ak viete, že najpravdepodobnejšie prípady použitia vašich metód / funkcií by boli ťažiť z kari.


1 pre odpoveď č. 2

Nejako, ale nie presne. Najväčší rozdiel je v tom, že mať viac zoznamov parametrov nám umožňuje jednoduchšie používať funkciu bez zadania všetkých parametrov.

Napríklad definujme vaše dve funkcie takto:

def sum1(f: Int => Int, a: Int, b: Int) = f(a + b)
def sum2(f: Int => Int)(a: Int, b: Int) = f(a + b)

Teraz umožníme definovať funkciu g ktorá berie ako parameter ďalšiu funkciu, ktorá berie dve Ints a vyrába Int

def g(f: (Int, Int) => Int) = f(3, 5)

Verzia programu sum s viacerými zoznamami parametrov nám umožňuje iba špecifikovať parametre prvého zoznamu a potom odovzdať túto čiastočne použitú funkciu g:

g(sum2(_ + 1))

Je to veľmi jednoduché a veľmi čisté.

Bez samostatných zoznamov parametrov, ako v sum1, musíme napísať výraz lambda, aby sme ukázali, kde a a b parametre pochádzajú z:

g((a: Int, b: Int) => sum1(_ + 1, a, b))