A differenza di C# (e Java e C e C++) che sono linguaggi basati su istruzioni, Scala è un linguaggio basato su espressioni. Questo è principalmente un grande vantaggio in termini di compostezza e leggibilità, ma in questo caso la differenza ti ha morsicato.
metodo A Scala restituisce implicitamente il valore dell'ultima espressione nel metodo
scala> def id(x : String) = x
id: (x: String)String
scala> id("hello")
res0: String = hello
In Scala praticamente tutto ciò è espressione. Le cose che assomigliano a dichiarazioni sono ancora espressioni che restituiscono un valore di un tipo chiamato Unità. Il valore può essere scritto come().
scala> def foo() = while(false){}
foo:()Unit
scala> if (foo() ==()) "yes!" else "no"
res2: java.lang.String = yes!
No compilatore per un linguaggio Turing-equivalente in grado di rilevare tutti i loop non fatale (c.f. Turing problema della terminazione) in modo maggior parte dei compilatori fare ben poco lavoro per rilevare eventuali. In questo caso il tipo di "while (someCondition) {...}" è Unit, indipendentemente dalla Condizione, anche se è costante.
scala> def forever() = while(true){}
forever:()Unit
Scala determina che il tipo restituito dichiarato (stringa) non è compatibile con il tipo di rendimento effettivo (Unit), che è il tipo dell'ultima espressione (mentre ...)
scala> def wtf() : String = while(true){}
<console>:5: error: type mismatch;
found : Unit
required: String
def wtf() : String = while(true){}
Risposta: aggiungere un'eccezione alla fine
scala> def wtfOk() : String = {
| while(true){}
| error("seriously, wtf? how did I get here?")
| }
wtfOk:()String
fonte
2012-05-29 17:26:54
FWIW - ci sono [ molti modi per implementare nuovamente la logica retry] (http://stackoverflow.com/q/7930814/115478). – leedm777
+1 Grazie per i suggerimenti e ulteriori informazioni sulle insidie di Tailrec. –