2017-02-01 7 views
1

Ich schreibe eine Funktion und habe ein seltsames Problem. Ich bin mit Pattern-Matching, und dann eine interne Funktion, die verwendet eine etwas verändert, aber fast identisches Muster und es kompiliert nicht:Verschachtelte Funktion Skews Rückgabetyp des übergeordneten Elements

def isTriangular(n: Int): Boolean = { 
    n match { 
    case n if n < 1 => false 
    case _ => triangularMaths(n, 1) 
    } 

    def triangularMaths(j:Int, counter: Int): Boolean = (j, counter) match { 
    case _ if j-counter == 0 => true 
    case _ if j-counter < 0 => false 
    case _ => triangularMaths(j-counter, counter+1) 
    } 
} 

Die Lösung für dieses ist ich ihn einfach an zwei separate Methoden machen, und sie arbeiten, solange triangularMaths nicht verschachtelt ist. Da jedoch triangularMaths nur für triangular spezifisch ist, möchte ich, dass es verschachtelt wird. Allerdings, wenn ich das tue, beschwert sich mein Compiler und sagt mir, dass ich Unit zurückgebe, anstatt die erwartete . Dies ist nicht ganz sinnvoll, da, sobald die ursprünglichen Groß- und Kleinschrei- bungen aufgelöst sind und "true" oder "false" zurückgegeben wird, sie bis zum Ende der Methode gehen soll. Was ist das Problem?

+0

Hinweis: Der Rückgabewert einer Methode ist der Wert des letzten in der Methode ausgewerteten Ausdrucks. Tipp # 2: Was ist der letzte in der Methode ausgewertete Ausdruck? Tipp # 3: Was ist der Wert einer Funktionsdefinition? –

Antwort

3

Dies passiert, weil Ihre Methode die letzte Deklaration im Gültigkeitsbereich ist, die den Compiler den Unit Wert als Rückgabetyp emittiert. Dekompiliert Code sieht wie folgt aus:

def main(args: Array[String]): Unit = { 
    def isTriangular(n: Int): Boolean = { 
    n match { 
     case (n @ _) if n.<(1) => false 
     case _ => triangularMaths(n, 1) 
    }; 
    def triangularMaths(j: Int, counter: Int): Boolean = scala.Tuple2.apply[Int, Int](j, counter) match { 
     case _ if j.-(counter).==(0) => true 
     case _ if j.-(counter).<(0) => false 
     case _ => triangularMaths(j.-(counter), counter.+(1)) 
    }; 
    () 
    }; 

Zuerst definieren triangularMaths, und dann rufen:

def isTriangular(n: Int): Boolean = { 
    def triangularMaths(j: Int, counter: Int): Boolean = (j, counter) match { 
    case _ if j - counter == 0 => true 
    case _ if j - counter < 0 => false 
    case _ => triangularMaths(j - counter, counter + 1) 
    } 

    n match { 
    case n if n < 1 => false 
    case _ => triangularMaths(n, 1) 
    } 
} 

Eine andere Möglichkeit wäre, die Mustererkennung auf einen Wert zuweisen, und kehren dann diesen Wert als letzte Ausdruck der Methode. Aber das würde den Compiler über Vorwärtsreferenz beschweren, die Sie beheben könnten, indem Sie stattdessen eine lazy val machen. Ich würde den Nachbestellungsansatz beibehalten.

+0

Aha, danke. Ich hatte versucht, ein var 'b: boolean = false' als erste Zeile von' isTriangular' zu setzen und dann die zweite Zeile von 'n match' zu setzen:' case _ => b == triangularMaths (n, 1) ' und dann 'b' direkt vor der schließenden Klammer der ganzen Sache zurückgeben, aber es würde sich nicht an die Änderung zu 'b' erinnern, wenn es zu wahr ausgewertet wurde. – NateH06

Verwandte Themen