/ / scala literał funkcji i metody oraz podkreślenie - scala, programowanie funkcyjne

funkcja dosłowna i metody oraz podkreślenie - scala, funkcjonalne programowanie

Mam bardzo prosty fragment kodu, którego nie jestem w stanie pojąć. Czytam literały funkcji i metody. Robię to w repl.

scala> val v = (a:Int, b:Int, c:Int) => {a+b+c}
v: (Int, Int, Int) => Int = $$Lambda$1368/1731643198@4ae730ca

scala> val v1 = v(1,2,_:Int)
v1: Int => Int = $$Lambda$1369/903167315@93d6f4

scala> v1 (10)
res29: Int = 13

scala>

scala> val v2 = v _
v2: () => (Int, Int, Int) => Int = $$Lambda$1370/5485285@7dd5d17a

scala> val v3 = v2()
v3: (Int, Int, Int) => Int = $$Lambda$1368/1731643198@4ae730ca

scala> val v4 = v3(1,2,3)
v4: Int = 6

scala> def sumMe(a:Int, b:Int, c:Int) = { a+b+c}
sumMe: (a: Int, b: Int, c: Int)Int

scala> val v7 = sumMe _
v7: (Int, Int, Int) => Int = $$Lambda$1371/906350712@6c86938f

scala> v7(1,2,3)
res30: Int = 6

Potrzebuję pomocy w zrozumieniu tego, co się dziejepowyżej. Zacznę od dołu kodu. Kiedy tworzę metodę sumMe i przypisuję ją do „v7” z „_” po prawej stronie, wiem, że nie wykonuję metody. Wyjście val v7= sumMe_ jest dla mnie całkiem jasne, ponieważ po prostu mówi mi, że v7 przyjmie 3 parametry i zwróci int. Jak dotąd wydaje się OK.

Teraz, kiedy przejdę do mojego `val v1 = v (1,2, _: Int), nadal mogę skorelować, że utworzy obiekt funkcji i przypisze do v1 i faktycznie używam Scali Metoda Apply1 jest tym, co ja widzę.

Mam nadzieję, że jak dotąd dobrze to rozumiem. Jeśli moje rozumienie powyżej jest słuszne, to, co powoduje największe zamieszanie, to val v2 = v _. I na podstawie tego, co widzę, muszęnazwij to inaczej. Zasadniczo nie jestem w stanie zrozumieć, dlaczego v2 różni się od v7. v2 nie przyjmuje żadnych argumentów i daje mi funkcję, którą mogę wywołać. Jeśli tak jest zawsze w przypadku literałów funkcji, które zdefiniowałem jako val v = ..., kiedy to zrobię val v1 = v(1,2,:_Int) dlaczego nie dostaję tego od Scala v1:()=>Int=>Int który jest podobny do v2"s case.

I wreszcie, dlaczego nie v7=sumMe _ nie dawaj mi tego samego wyjścia, co val v2 = v_

Odpowiedzi:

2 dla odpowiedzi № 1

W Scali różnicujemy metody od Funkcje. Kiedy zdefiniujesz sumMe, ponownie definiujesz metodę, podczas gdy inne deklaracje są funkcjami. Metody w Scali, nie są typami wartości, co oznacza, że ​​sama metoda nie ma wartości. Podczas próby przypisania go do wartości wywoływana jest niejawna konwersja ekspansja eta to jest zrobione, aby przekonwertować go na odpowiedni typ funkcji. Ze specyfikacji:

Typy metod nie istnieją jako typy wartości. Jeśli używana jest nazwa metody jako wartość, jej typ jest niejawnie konwertowany na odpowiedni plik typ funkcji.

Teraz, gdy mamy już wiedzę o metodach i funkcjach, przeanalizujmy, co się dzieje.

Kiedy tworzę metodę sumMe i przypisz go do "v7" z "_" po prawej, wiem, że nie wykonuję metody

Zgadza się. Kiedy to zrobisz sumMe _, używasz rozwijania eta do konwersji metody na funkcję.

Teraz, kiedy idę do mojego val v1 = v(1, 2, _: Int), Nadal mogę to skorelować utworzy obiekt funkcji i przypisze go do v1

Znowu masz rację. v1 jest teraz częściowo zastosowaną funkcją typu Function1[Int, Int].

Zasadniczo nie jestem w stanie zrozumieć, dlaczego v2 różni się od v7.

Co jest v2? Jest to obiekt funkcji, który został utworzony poprzez częściowe zastosowanie istniejącego obiektu funkcji. Ponieważ ta funkcja typu Function3[Int, Int, Int, Int] jest już naprawiona na liście parametrów, a jej częściowe zastosowanie powoduje tylko zagnieżdżenie go w innym obiekcie funkcji, teraz typu Function0, czyniąc to Function0[Function3[Int, Int, Int, Int]].


2 dla odpowiedzi nr 2

W Scali funkcje mają wartość, co oznacza, że ​​możeszprzypisać dowolną funkcję w zmiennej. Za każdym razem, gdy zastosujesz symbol zastępczy („_”) przed def, przekształci on def w funkcję o tych samych typach danych wejściowych i wyjściowych. Jeśli zastosujesz symbol zastępczy przed wartością, przekształci się on w funkcję, która przyjmuje jednostkę jako dane wejściowe i zwraca wartość jako wyjście ** [() => T] **. na przykład:

 scala> val a = 2
a: Int = 2

scala> val fun1  = a _
fun1: () => Int = <function0>

scala> def sum(a:Int, b:Int) = a+ b
sum: (a: Int, b: Int)Int

scala> val fun2 = sum _
fun2: (Int, Int) => Int = <function2>

za każdym razem, gdy próbujesz przekazać częściowe parametry wejściowe w „def”, to zwróci zastosowana częściowo funkcjonować. Na przykład:

scala> val fun3 = sum(1,_:Int)
fun3: Int => Int = <function1>

fun3 nazywana jest funkcją częściowo zastosowaną.


1 dla odpowiedzi nr 3

Jest coś, dla czego trzeba oczyścić function i method,

  1. funkcjonować: Używamy val i var zdefiniować function, często jest to plik Anonymous Function, W Scala, tam są Function0, Function1, Function2 ... dla tych Anonymous Functioni typ funkcji, taki jak: (T0, T1...TN) => U.

    więc funkcjonować v faktycznie jest Function3 z 3 parametry.

  2. metoda: to jest przyzwyczajone def deklarować z method ciało z parametry i return type.

Dla val v2 = v _ faktycznie równa się val v2 = () => v, tam symbol wieloznaczny _ rozszerzy się do () => v, i v2 oznacza, że ​​jest to funkcja służąca do tworzenia innej funkcji (v) bez parametru val v3 = v2() znaczy invoke v2() tworzyć v funkcji, więc zasadniczo v3 równy v.

Dla val v7 = sumMe _ to znaczy metoda konwersji sumMe do funkcji, w tym symbolu wieloznacznego _ rozszerzy się do (a: Int, b: Int, c: Int) => sumMe(a, b, c) , więc sumMe _ stworzy nową funkcję, która jest zasadniczo równa v, Jeśli użyjesz v7 _ to również stworzy to samo function lubić val v2 = v _.

Odniesienie:

Różnica między metodą a funkcją w Scali