2012-11-06 17 views
5

Ricevo un errore sulla linea:Errore classe Scala: metodo ricorsivo printExpr bisogno risultato di tipo

case Sum(l, r) => printExpr(l); print("+"); printExpr(r) 

errore è:

metodo ricorsivo printExpr bisogno tipo di risultato

Questo codice mi sembra a posto, cosa sto sbagliando?

abstract class Expr { 

    case class Num(n: Int) extends Expr 
    case class Sum(l: Expr , r: Expr) extends Expr 
    case class Prod(l: Expr, r: Expr) extends Expr 

    def evalExpr(e: Expr): Int = e match { 
    case Num(n) => n 
    case Sum(l, r) => evalExpr(l) + evalExpr(r) 
    case Prod(l, r) => evalExpr(l) * evalExpr(r) 
    } 

    def printExpr(e: Expr) = e match { 
    case Num(n) => print(" " + n + " ") 
    case Sum(l, r) => printExpr(l); print("+"); printExpr(r) 
    case Prod(l, r) => printExpr(l); print("x"); printExpr(r) 
    } 
} 

risposta

8

metodi ricorsivi in ​​Scala hanno bisogno di un tipo di ritorno esplicitamente dichiarato, come afferma il messaggio di errore.

La ragione è che Scala deduce il tipo di ritorno del metodo dai tipi utilizzati nel corpo del metodo. Quando il tipo di ritorno del metodo influenza i tipi utilizzati nel corpo del metodo (poiché si chiama in modo ricorsivo), Scala non è in grado di capire quale tipo deve essere assegnato al metodo, quindi è necessario farlo nell'origine codice (come si ha con evalExpr, dove si dice esplicitamente che restituisce un Int).

In questo caso, si desidera restituire il tipo Unit, che è il tipo di valori non interessanti senza informazioni. In genere, la chiamata di un metodo con tipo di ritorno Unit viene eseguita solo per i relativi effetti collaterali (ad esempio print).

in modo da poter modificare la riga di intestazione di printExpr a:

def printExpr(e: Expr) : Unit = e match { 

In alternativa, Scala ha un po 'di zucchero sintattico per la dichiarazione di "procedure". Puoi pensare ad una "procedura" come non restituire nulla, e semplicemente eseguire un codice, ma in realtà ogni metodo in Scala restituisce ; le "procedure" sono solo metodi che restituiscono il tipo Unit. La sintassi per farlo è omettere lo = dopo l'intestazione del metodo, ma poi deve circondare il corpo del metodo con parentesi graffe (anche se è una singola espressione, come il tuo match). Così si potrebbe fare:

def printExpr(e: Expr) { 
    e match { 
    ... 
    } 
} 

da evitare dichiarando esplicitamente Unit.

1

Dare un tipo di ritorno per printExpr(e : Expr) come String o Expr ad esempio

printExpr(e : Expr): Expr 
printExpr(e : Expr): String 
4

Scala compilare tipi dedurre cativi per i metodi ricorsivi, quindi è necessario dichiarare in modo esplicito:

def printExpr(e: Expr): Unit = e match { 
Problemi correlati