2010-09-05 4 views
92

, die drei Ausdrucksweisen die gleiche Funktion f(a) := a + 1 Gegeben:Unterschiede zwischen diesen drei Möglichkeiten, eine Funktion in Scala

val f1 = (a:Int) => a + 1 
def f2 = (a:Int) => a + 1 
def f3:(Int => Int) = a => a + 1 

Wie diese Definitionen unterscheiden? Die REPL keine offensichtlichen Unterschiede zeigen:

scala> f1 
res38: (Int) => Int = <function1> 
scala> f2 
res39: (Int) => Int = <function1> 
scala> f3 
res40: (Int) => Int = <function1> 
+11

Sie sollten, dass im zweiten Block oben beachten Sie, dass die Bewertung 'f1' im REPL den Wert zeigt statisch' f1' gebunden, während die Bewertung 'f2 'und' f3' zeigen das Ergebnis von * Aufruf * dieser Methoden. Insbesondere wird jedes Mal, wenn entweder 'f2' oder' f3' aufgerufen wird, eine neue 'Function1 [Int, Int]' - Instanz erzeugt, während 'f1' für immer die gleiche' Funktion1 [Int, Int] 'ist. –

+0

@RandallSchulz Angesichts der Tatsache, dass die val-Version keine neue Funktionsinstanz benötigt, warum sollte man in diesem Fall def verwenden? – virtualeyes

+2

@virtualeyes Die einzige Situation, an die ich mich erinnern kann, wo man Defs sieht, die FunctionN-Werte [...] liefern, ist in der Kombinator-Parser-Bibliothek. Es ist nicht sehr üblich, Methoden zu schreiben, die Funktionen liefern, und praktisch niemals würde man ein def verwenden, um viele Kopien einer semantisch/funktional unveränderlichen Funktion zu erhalten. –

Antwort

112

f1 ist eine Funktion, die eine ganze Zahl nimmt und gibt eine ganze Zahl ist.

f2 ist eine Methode mit Nullität, die eine Funktion zurückgibt, die eine Ganzzahl annimmt und eine ganze Zahl zurückgibt. (Wenn Sie später f2 bei REPL geben, wird es ein Aufruf der Methode f2.)

f3 ist die gleiche wie f2. Sie verwenden dort nur keine Typinferenz.

+6

Warum 'f1' ist eine' Funktion' und 'f2' ist eine' Methode'? – Freewind

+17

@Freewind, eine Funktion ist ein Objekt mit einer Methode namens 'apply'. Eine Methode ist eine Methode. – missingfaktor

+0

Super Antwort. Frage: Du sagst, f2 hat null Arität, aber ist es nicht unär? https: //en.wikipedia.org/wiki/Arity "Eine nullare Funktion benötigt keine Argumente. Eine unäre Funktion benötigt ein Argument." Nur neugierig! –

122

Innerhalb einer Klasse wird val bei Initialisierung ausgewertet, während def nur ausgewertet wird, wenn und jedes Mal die Funktion aufgerufen wird. Im folgenden Code sehen Sie, dass x bei der ersten Verwendung des Objekts ausgewertet wird, nicht jedoch beim Zugriff auf das x-Element. Im Gegensatz dazu wird y nicht ausgewertet, wenn das Objekt instanziiert wird, sondern wird jedes Mal ausgewertet, wenn auf das Element zugegriffen wird.

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) 
+0

@JacobusR ist das nur innerhalb einer Klasse wahr? –

+0

zum Beispiel: Scala> var b = 5 b: Int = 5 Scala> val a: (Int => Int) = x => x + b a: Int => Int = scala> a (5) res48: Int = 10 scala> b = 6 b: Int = 6 Scala> a (5) res49: Int = 11 I erwartete a (5) 10 zurückzukehren, und den Wert von b inline gewesen sein –

+0

@AndrewCassidy die Funktion 'a' ist unveränderlich und ausgewertet bei der Initialisierung, aber' b' bleibt ein veränderbarer Wert. Daher wird der Bezug auf "b" während der Initialisierung eingestellt, aber der durch "b" gespeicherte Wert bleibt veränderbar. Aus Spaß könnten Sie nun ein neues 'val b = 123' erstellen. Danach wird Ihr 'a (5)' immer 11 geben, da das 'b' jetzt ein komplett neuer Wert ist. – Jack

3

Ausführen einer Definition wie def x = e nicht den Ausdruck e bewerten. Stattdessen wird e ausgewertet, wenn x verwendet wird. Alternativ bietet Scala einen Wert Definition val x = e, die dem rechtsseitigen e als Teil der Bewertung der Definition nicht auswertet. Wenn anschließend x verwendet wird, wird es sofort durch den vorberechneten Wert von und ersetzt, so dass der Ausdruck nicht erneut ausgewertet werden muss.

Scala By Example von Martin Odersky

Verwandte Themen