2016-12-10 2 views
0

Komplette Anfänger zu Scala und versuchen gerade jetzt, die Grundlagen herauszufinden.Scala Type Mismatch Unit anstelle von Int

Als Teil eines Tutorials versuche ich eine Funktion zu erstellen, die das größte Element in einer Liste von ganzen Zahlen zurückgibt. Um dies zu erreichen Ich habe zusammen (vorläufig) einen den folgenden Code:

def max(xs: List[Int]): Int = 
    if (xs.isEmpty) 
    throw new java.util.NoSuchElementException 
    else 
    findMax(xs.head, xs.tail) 

def findMax(a: Int, b: List[Int]) { 
    if (b.isEmpty) return a 

    if (a > b.head) 
    findMax(a, b.tail) 
    else 
    findMax(b.head, b.tail) 
} 

Allerdings, wenn ich versuche, es zu kompilieren ich eine Art Fehlermeldung erhalten für Zeile 5.

[error] /scala/example/src/main/scala/example/Lists.scala:5: type mismatch; 
[error] found : Unit 
[error] required: Int 
[error]   findMax(xs.head, xs.tail) 

Ich muss Ich bin ein wenig verwirrt wegen dieser Fehlermeldung, da ich nicht verstehe, wie der Compiler denkt, dass ich versuche, einen Einheitentyp zu übergeben, vorausgesetzt, die Logik stellt sicher, dass eine Liste vor dieser Zeile nicht leer ist.

Kann jemand helfen, das Problem hier zu klären?

Antwort

5

Scala hat zwei Konstrukte zur Definition einer Funktion:

def doSomething(a: Int) { a + 3 } 

und

def doSomethingElse(b: Int) = { b + 3 } 

Die erste ist als Verfahren Syntax bekannt, und es wird abgeraten, da sie zu einer schlechten Annahmen und verwirrend Code führt . Der Unterschied zwischen diesen beiden Funktionen besteht darin, dass doSomethingUnit zurückgibt, während doSomethingElseInt zurückgibt. Wenn Sie keine = einschließen, gibt Ihre Funktion nichts zurück (mit anderen Worten, sie gibt Unit zurück).

Diese

def doSomething(a: Int) { a + 3 } 

entspricht

def doSomething(a: Int): Unit = { a + 3 } 

Sie möchten Ihre Funktion findMax ein Int zurückgeben, aber weil Sie die = aufhörte, Scala sagt es Unit zurückgibt. Dies ist die Ursache für Ihren Kompilierungsfehler. Sie können dieses Problem beheben, indem entweder das Schreiben

def findMax(a: Int, b: List[Int]) = { 

oder

def findMax(a: Int, b: List[Int]): Int = { 

In der Regel sollten Sie nie Prozedur Syntax. Verwenden Sie immer =, auch wenn Sie den endgültigen Rückgabetyp endgültig auf Typrückschluss setzen.


Es soll beachtet werden, dass der erste Ansatz in einem Compiler-Fehler tatsächlich führen könnte, weil Sie return in Ihrer Funktion verwendet. Funktionen, die explizit return aufrufen, müssen den Typ angeben, den sie im Funktionskopf zurückgeben. Da es sich bei Scala um eine ausdrucksbasierte Sprache handelt, ist jede Anweisung ein Ausdruck und gibt somit einen Wert zurück. Sie können Ihre findMax Funktion umschreiben nicht return müssen, wie folgt:

def findMax(a: Int, b: List[Int]): Int = { 
    if (b.isEmpty) 
    a 
    else if (a > b.head) 
    findMax(a, b.tail) 
    else 
    findMax(b.head, b.tail) 
} 
+0

Prozedur Syntax unter -Xfuture ist veraltet. Ich denke, das ist der Grund. –

+0

Danke, du hast noch mehr Dinge geklärt, als mir klar wurde, dass sie mich verwirrten!Wenn ich eine weitere Frage stellen kann, können Sie erklären, was zurückgegeben wird, wenn eine Ausnahme ausgelöst wird? Konkret wollte ich ursprünglich die Zeilen 2 und 3 als Teil einer Wächterklausel anstelle einer if-else-Bedingung zusammenfügen, aber dies führt zu einer anderen Instanz des Typs Mismatch (Unit statt Int) und der Compiler sagt dann "xs" kein Wert, wenn er im Aufruf der findMax-Funktion verwendet wird. –

+0

'Würfe' ist ein ganz besonderer Fall. Es kommt nicht zurück. Es gibt auch keine Versuche, die den Typ der ausgelösten Ausnahme nicht abfangen. In diesem Fall ist der Rückgabetyp von "throws" oder "try" ein spezieller Bottom-Typ namens "Nothing". Es gibt keine Fälle von 'Nothing' - nicht einmal' null' ist 'Nothing'. 'Nothing' ist ein Subtyp von allem, so dass ein' if', das 'Nothing' in einem Zweig und ein' Int' in dem anderen zurückgibt, letztendlich 'Int' zurückgibt, da dies der niedrigste gemeinsame Typ seiner zwei Zweige ist. – Zeimyth