Biorąc pod uwagę trzy sposoby wyrażenia tej samej funkcji f(a) := a + 1
:
val f1 = (a:Int) => a + 1
def f2 = (a:Int) => a + 1
def f3:(Int => Int) = a => a + 1
Czym różnią się te definicje? REPL nie wskazuje żadnych oczywistych różnic:
scala> f1
res38: (Int) => Int = <function1>
scala> f2
res39: (Int) => Int = <function1>
scala> f3
res40: (Int) => Int = <function1>
f1
w REPL pokazuje wartość statycznie związanąf1
podczas obliczaniaf2
if3
pokazuje wynik wywołania tych metod. W szczególności nowaFunction1[Int, Int]
instancja jest tworzona za każdym razem , gdy jest wywoływanaf2
lubf3
jest wywoływana, podczas gdyf1
jest taka sama naFunction1[Int, Int]
zawsze.Odpowiedzi:
f1
jest funkcją, która przyjmuje liczbę całkowitą i zwraca liczbę całkowitą.f2
jest metodą z zerową arancją, która zwraca funkcję, która przyjmuje liczbę całkowitą i zwraca liczbę całkowitą. (Kiedyf2
później wpiszesz REPL, stanie się to wywołaniem metodyf2
).f3
jest taki sam jakf2
. Po prostu nie stosujesz tam wnioskowania o typie.źródło
f1
afunction
if2
jestmethod
?apply
. Metoda to metoda.f2
sam w sobie nie przyjmuje żadnych argumentów. Obiekt funkcji, który zwraca, robi.Wewnątrz klasy
val
jest oceniany podczas inicjalizacji, natomiastdef
jest oceniany tylko wtedy, gdy i za każdym razem wywoływana jest funkcja. W poniższym kodzie zobaczysz, że x jest oceniane przy pierwszym użyciu obiektu, ale nie ponownie, gdy uzyskuje się dostęp do elementu x. W przeciwieństwie do tego wartość y nie jest oceniana, gdy tworzona jest instancja obiektu, ale jest oceniana za każdym razem, gdy uzyskuje się dostęp do elementu członkowskiego.class A(a: Int) { val x = { println("x is set to something"); a } def y = { println("y is set to something"); a } } // Prints: x is set to something val a = new A(1) // Prints: "1" println(a.x) // Prints: "1" println(a.x) // Prints: "y is set to something" and "1" println(a.y) // Prints: "y is set to something" and "1" println(a.y)
źródło
a
jest niezmienna i oceniana podczas inicjalizacji, aleb
pozostaje zmienną wartością. Zatem odniesienie dob
jest ustawiane podczas inicjalizacji, ale wartość przechowywana przezb
pozostaje zmienna. Dla zabawy możesz teraz stworzyć nowyval b = 123
. Po tyma(5)
zawsze będziesz dawał 11, ponieważb
jest to teraz zupełnie nowa wartość.Wykonanie definicji takiej jak def x = e nie spowoduje oceny wyrażenia e . Zamiast tego e jest oceniane zawsze, gdy używane jest x . Alternatywnie Scala oferuje definicję wartości val x = e , która ocenia prawą stronę e jako część oceny definicji. Jeśli następnie zostanie użyte x , jest natychmiast zastępowane przez wstępnie obliczoną wartość e , dzięki czemu wyrażenie nie musi być ponownie obliczane.
źródło