Przeczytałem Scala Functions (część Another tour of Scala ). W tym poście stwierdził:
Metody i funkcje to nie to samo
Ale nic nie wyjaśnił. Co on chciał powiedzieć?
Przeczytałem Scala Functions (część Another tour of Scala ). W tym poście stwierdził:
Metody i funkcje to nie to samo
Ale nic nie wyjaśnił. Co on chciał powiedzieć?
Odpowiedzi:
Jim napisał o tym prawie na swoim blogu , ale zamieszczam tutaj informacje w celu odniesienia.
Najpierw zobaczmy, co mówi nam specyfikacja Scala. Rozdział 3 (typy) mówi nam o typach funkcji (3.2.9) i typach metod (3.3.1). Rozdział 4 (podstawowe deklaracje) mówi o deklaracji wartości i definicjach (4.1), deklaracji zmiennych i definicjach (4.2) oraz deklaracjach i definicjach funkcji (4.6). Rozdział 6 (wyrażenia) mówi o funkcjach anonimowych (6.23) i wartościach metod (6.7). Co ciekawe, o wartościach funkcji mówi się jeden raz w 3.2.9 i nigdzie indziej.
Typ funkcji jest (w przybliżeniu) rodzaj postaci (T1, ..., Tn) => U , która jest skrótem dla tej cechy
FunctionN
w bibliotece standardowej. Anonimowe funkcje i metody Wartości mają typy funkcji, a typy funkcji mogą być używane jako część deklaracji i definicji wartości, zmiennych i funkcji. W rzeczywistości może być częścią typu metody.Metoda Type to typ non-wartość . Oznacza to, że nie ma wartości - żadnego obiektu, żadnej instancji - z typem metody. Jak wspomniano powyżej, wartość metody faktycznie ma typ funkcji . Typ metody to
def
deklaracja - wszystkodef
oprócz ciała.Wartość Deklaracje i Definicje i deklaracje zmiennych i definicje są
val
ivar
deklaracje, w tym zarówno rodzajem i wartością - co może być, odpowiednio, Typ funkcji i anonimowych funkcji lub wartości Method . Zauważ, że w JVM te (wartości metod) są implementowane za pomocą tego, co Java nazywa „metodami”.Funkcja deklaracji jest
def
deklaracja, w tym rodzaj i ciała . Część typu jest typem metody, a treść jest wyrażeniem lub blokiem . Jest to również zaimplementowane w JVM za pomocą tego, co Java nazywa „metodami”.Wreszcie, funkcja anonimowa jest instancją typu funkcji (tj. Instancją cechy
FunctionN
), a wartość metody jest taka sama! Różnica polega na tym, że wartość metody jest tworzona z metod, albo po poprawce podkreślenia (m _
jest to wartość metody odpowiadająca „deklaracji funkcji” (def
)m
), albo w procesie zwanym eta-rozszerzeniem , który jest jak rzutowanie automatyczne z metody funkcjonować.Tak mówią specyfikacje, więc postawię to na wstępie: nie używamy tej terminologii! Prowadzi to do zbyt dużego nieporozumienia między tak zwaną „deklaracją funkcji” , która jest częścią programu (rozdział 4 - podstawowe deklaracje), a „funkcją anonimową” , która jest wyrażeniem, a „typem funkcji” , która jest: no typ - cecha.
Poniższa terminologia, stosowana przez doświadczonych programistów Scala, wprowadza jedną zmianę w stosunku do terminologii specyfikacji: zamiast powiedzieć deklarację funkcji , mówimy metodę . Lub nawet deklaracja metody. Ponadto zauważamy, że deklaracje wartości i deklaracje zmiennych są również metodami do celów praktycznych.
Biorąc pod uwagę powyższą zmianę terminologii, oto praktyczne wyjaśnienie tego rozróżnienia.
Funkcja jest obiektem, który zawiera jedną z
FunctionX
cech, takich jakFunction0
,Function1
,Function2
, itd. To może być tymPartialFunction
, jak dobrze, co rzeczywiście rozszerzaFunction1
.Zobaczmy podpis typu dla jednej z tych cech:
Ta cecha ma jedną abstrakcyjną metodę (ma też kilka konkretnych metod):
I to mówi nam wszystko, co trzeba o tym wiedzieć. Funkcja ma
apply
metodę, która odbiera N parametry typu T1 , T2 , ..., TN , i powroty coś typuR
. Jest przeciwny do otrzymywanych parametrów, a drugi do wyniku.Ta wariancja oznacza, że a
Function1[Seq[T], String]
jest podtypemFunction1[List[T], AnyRef]
. Bycie podtypem oznacza, że można go użyć zamiast niego. Łatwo zauważyć, że jeśli mam zadzwonićf(List(1, 2, 3))
i spodziewać sięAnyRef
oddzwaniania, oba powyższe typy działałyby.Jakie jest podobieństwo metody i funkcji? Cóż, jeśli
f
jest funkcją im
jest metodą lokalną dla zakresu, to oba można wywołać w następujący sposób:Te połączenia są w rzeczywistości różne, ponieważ pierwszy to tylko cukier syntaktyczny. Scala rozwija go do:
Co oczywiście jest wywołaniem metody na obiekcie
f
. Funkcje mają także inne cukry składniowe na swoją korzyść: literały funkcyjne (właściwie dwa) i(T1, T2) => R
podpisy tekstowe. Na przykład:Innym podobieństwem między metodą a funkcją jest to, że pierwszą można łatwo przekonwertować na drugą:
Scala rozszerzy to , zakładając, że
m
typem jest(List[Int])AnyRef
(Scala 2.7):W Scali 2.8 używa
AbstractFunction1
klasy, aby zmniejszyć rozmiary klas.Zauważ, że nie da się przekonwertować na odwrót - z funkcji na metodę.
Metody mają jednak jedną dużą zaletę (cóż, dwie - mogą być nieco szybsze): mogą odbierać parametry typu . Na przykład, chociaż
f
powyżej można koniecznie określić typList
otrzymywanego (List[Int]
w przykładzie),m
można go sparametryzować:Myślę, że w zasadzie obejmuje to wszystko, ale chętnie uzupełnię to odpowiedziami na wszelkie pytania, które mogą pozostać.
źródło
val f = m
kompilatoraval f = new AnyRef with Function1[List[Int], AnyRef] { def apply(x$1: List[Int]) = this.m(x$1) }
, powinieneś zauważyć, że metodathis
wewnątrzapply
nie odnosi się doAnyRef
obiektu, ale do obiektu, w którego metodzieval f = m _
jest oceniana ( zewnętrznathis
, że tak powiem ), ponieważthis
należy do wartości uchwyconych przez zamknięcie (jak np.return
jak wskazano poniżej).Jedną dużą praktyczną różnicą między metodą a funkcją jest to, co
return
oznacza.return
tylko zawsze wraca z metody. Na przykład:Zwracanie z funkcji zdefiniowanej w metodzie powoduje nielokalny zwrot:
Natomiast powrót z metody lokalnej zwraca tylko z tej metody.
źródło
for (a <- List(1, 2, 3)) { return ... }
? To zostaje pozbawione cukru do zamknięcia.return
zwrócić wartość od funkcji, a część formyescape
ibreak
lubcontinue
do powrotu z metod.Programowanie w Scala Wydanie drugie. Martin Odersky - Lex Spoon - Bill Venners
źródło
Pozwól, że masz listę
Zdefiniuj metodę
Zdefiniuj funkcję
Metoda akceptowania argumentu
Definiowanie funkcji za pomocą val
Argument funkcji jest opcjonalny
Argument do metody jest obowiązkowy
Sprawdź następujący samouczek, który wyjaśnia przekazywanie innych różnic przykładami, takimi jak inny przykład różnicy z funkcją Metoda Vs, Używanie funkcji jako zmiennych, tworzenie funkcji, która zwróciła funkcję
źródło
Funkcje nie obsługują wartości domyślnych parametrów. Metody działają. Przekształcenie z metody na funkcję traci wartości domyślne parametrów. (Scala 2.8.1)
źródło
Jest tutaj fajny artykuł , z którego pochodzi większość moich opisów. Krótkie porównanie funkcji i metod dotyczących mojego zrozumienia. Mam nadzieję, że to pomoże:
Funkcje : Są w zasadzie przedmiotem. Dokładniej, funkcje są obiektami z zastosowaniem metody; Dlatego są nieco wolniejsze niż metody ze względu na narzut. Jest podobny do metod statycznych w tym sensie, że są one niezależne od obiektu, który ma zostać wywołany. Prosty przykład funkcji jest jak poniżej:
Linia powyżej to nic innego jak przypisanie jednego obiektu do drugiego, np. Object1 = object2. W rzeczywistości obiekt2 w naszym przykładzie jest funkcją anonimową, dlatego lewa strona otrzymuje z tego powodu typ obiektu. Dlatego teraz f1 jest obiektem (funkcją). Funkcja anonimowa jest w rzeczywistości instancją funkcji 1 [Int, Int], co oznacza funkcję z 1 parametrem typu Int i zwracaną wartością typu Int. Wywołanie f1 bez argumentów da nam podpis funkcji anonimowej (Int => Int =)
Metody : Nie są obiektami, ale są przypisane do instancji klasy, tj. Obiektu. Dokładnie taka sama jak metoda w java lub funkcje składowe w c ++ (jak zauważył Raffi Khatchadourian w komentarzu do tego pytania ) i itp. Prosty przykład metody jest podobny do poniższego :
Linia powyżej nie jest prostym przypisaniem wartości, ale definicją metody. Kiedy wywołujesz tę metodę z wartością 2, jak w drugim wierszu, x jest zastępowane przez 2, a wynik zostanie obliczony i otrzymasz 4 jako wynik. Tutaj pojawi się błąd, jeśli po prostu napisz m1, ponieważ jest to metoda i potrzebujesz wartości wejściowej. Za pomocą _ możesz przypisać metodę do funkcji takiej jak poniżej:
źródło
Oto świetny post Roba Norrisa, który wyjaśnia różnicę, oto TL; DR
z następującą definicją:
W skrócie ( wyciąg z bloga ):
Kiedy definiujemy metodę, widzimy, że nie możemy jej przypisać do
val
.Należy również zwrócić uwagę na typ z
add1
, co nie wygląda normalnie; nie można zadeklarować zmiennej typu(n: Int)Int
. Metody nie są wartościami.Jednak dodając operator postfiksu rozszerzenia η (η jest wymawiane jako „eta”), możemy przekształcić metodę w wartość funkcji. Zwróć uwagę na rodzaj
f
.Efektem
_
jest wykonanie równoważnika następujących czynności: konstruujemyFunction1
instancję, która deleguje się do naszej metody.źródło
W Scali 2.13, w przeciwieństwie do funkcji, metody mogą przyjmować / zwracać
Jednak ograniczenia te są zniesione w dotty (Scala 3) według typów funkcji polimorficznych # 4672 , na przykład wersja dotty 0.23.0-RC1 umożliwia następującą składnię
Wpisz parametry
Parametry niejawne ( parametry kontekstu )
Zależne typy
Aby uzyskać więcej przykładów, zobacz testy / run / polymorphic-functions.scala
źródło
Praktycznie programista Scala musi znać tylko następujące trzy zasady, aby prawidłowo używać funkcji i metod:
def
i literały funkcji zdefiniowane przez=>
są funkcjami. Jest to zdefiniowane na stronie 143, rozdział 8, w książce Programowanie w Scali, wydanie 4.someNumber.foreach(println)
Po czterech edycjach Programowania w Scali nadal jest problem, aby ludzie rozróżnili dwie ważne koncepcje: funkcję i wartość funkcji, ponieważ wszystkie edycje nie dają jasnego wyjaśnienia. Specyfikacja języka jest zbyt skomplikowana. Odkryłem, że powyższe zasady są proste i dokładne.
źródło