2016-05-10 7 views
2

Ich habe eine Map, die die Möglichkeit, eine verschachtelte Karte des gleichen Typs haben. Jede dieser verschachtelten Karten hat eine Referenz zurück zur äußeren Karte."Kann nicht beweisen, dass Objekt <: <Try [U]" in abgeflachten Funktion

Ich habe ein findValue Verfahren definiert, welches die aktuelle Karte schaut durch, wenn er nichts finden, geht es an die Mutter, und so weiter, bis null erreicht, die die Eltern der äußersten SymbolTable ist.

Ich habe dieses Verhalten in eine Try, so dass ich auf Success und Failure übereinstimmen; aber um einen Typ a-la Try[Try[Try[ ... Try[TableVaue]... ]]] zu vermeiden, flachte ich den Ausgang ab.

Bei dem Versuch, flatten ich folgende Fehlermeldung erhalten, zu rufen: Cannot prove that Object <:< Try[U]

Hier sind die entsprechenden Bits des Codes:

class SymbolTable(val parentScope: SymbolTable) { 
    type TableValue = (TypeInfo, Option[Expression], Option[SymbolTable]) 

    private val contents: mutable.Map[String, TableValue] = mutable.Map.empty 

    private def findValue(key: String): Try[TableValue] = Try { 
    if (contents contains key) contents(key) 
    else parentScope findValue key 
    }.flatten 
} 

Also meine Frage ist: Wie kann ich diese Arbeit ohne großen Refactoring von meinem Code?

Antwort

5
if (contents contains key) contents(key) 
else parentScope findValue key 

Die Art dieses Ausdrucks ist die LUB von TableValue (das Ergebnis der contents.apply) und Try[TableValue] (das Ergebnis der findValue), und das ist AnyRef (oder java.lang.Object).

Die folgende würde wahrscheinlich funktionieren:

if (contents contains key) Try(contents(key)) 
else parentScope findValue key 

aber der ganze Ausdruck ist nicht gut. Try ist nur nützlich, wenn Sie nicht vermeiden müssen, Ausnahmen zu fangen, was hier nicht der Fall ist. Sie können Map#get perfekt verwenden, um eine Option abzurufen. Mit Option wird es viel einfacher:

def findValue(key: String): Option[TableValue] = 
    contents.get(key).orElse(parentScope.findValue(key)) 

Wenn parentScope sein kann null müssen Sie dagegen schützen auch Rückkehr None direkt.

+0

Sie haben wahrscheinlich Recht mit der Option, anstatt zu versuchen. Erfolg und Misserfolg sind nur in Bezug auf Absicht besser als Fehler/kein Fehler als Option ist –

+0

@ElectricCoffee Scala schreibe ich nicht sehr oft (nicht so oft, wie ich möchte), aber ich würde nicht erwarten, auf einen Baum zu gehen zu Erfolg führen Misserfolg [A] 'Ich würde' Einige [A] | erwarten Keine, da es sich um eine Suche handelt. Ich schreibe oft C# und rufe 'xs.FirstOrDefault()' und niemals 'xs.First()' auf, wenn ich nicht weiß, dass 'xs' nicht leer ist oder die Ausführung fehlschlagen soll, wenn sie leer ist. Ich möchte _not_ nicht mit 'InvalidOperationException' ('Sequenz enthält keine Elemente') 'abgefangen werden. Zugegeben, Scala-Idiome können in diesem Fall anders sein. –