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 № 1W 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
,
funkcjonować: Używamy
val
ivar
zdefiniowaćfunction
, często jest to plikAnonymous Function
, W Scala, tam sąFunction0
,Function1
,Function2
... dla tychAnonymous Function
i typ funkcji, taki jak:(T0, T1...TN) => U
.więc funkcjonować
v
faktycznie jestFunction3
z 3 parametry.metoda: to jest przyzwyczajone
def
deklarować zmethod
ciało z parametry ireturn 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