Wie @HristoIliev erwähnt, Ihre Methode nicht Schwanz rekursiv, weil der finally
Aufruf der Endaufruf sein ist nicht gewährleistet werden kann. Dies bedeutet, dass jede Methode, die try
auf diese Weise verwendet, nicht tail rekursiv ist. Siehe auch this answer, auch.
Die Methode erneut aufrufen ist eine seltsame Art, etwas wiederholt zu versuchen, bis es erfolgreich ist, weil es in jedem Stadium eine Ausnahme auslöst, die Sie vermutlich nicht verarbeiten. Stattdessen würde ich argumentieren, einen funktionalen Ansatz mit Try
zu verwenden und Fehler aus einer Sicht zu nehmen, bis der Vorgang erfolgreich ist. Der einzige Nachteil dieses Ansatzes ist, dass er keine Ausnahmen für Sie bereithält (was auch ein Vorteil sein kann!).
def tryAll[A](xs: List[A])(f: A => Unit): Unit =
xs.view.map(x => Try(f(x))).takeWhile(_.isFailure).force
scala> val list = List(0, 0, 0, 4, 5, 0)
scala> tryAll(list)(a => println(10/a))
2
Wenn Sie wirklich die Ausnahmen behandeln wollen (oder nur die letzte Ausnahme), können Sie den Rückgabetyp von tryAll
zu List[Try[Unit]]
ändern (oder einfach Try[Unit]
wenn Sie den Code ändern, um nur die letzten nehmen). Es ist besser, wenn der Rückgabetyp der Methode einen Teil dessen beschreibt, was er tatsächlich tut - möglicherweise Fehler zurückgibt.
Die Funktion ist nicht tail rekursiv, da in dem Fall, dass eine Ausnahme ausgelöst wird, der 'finally' Block nicht der letzte Code ist, der ausgeführt wird. –
@HristoIliev: Ich sehe - wie kann ich das dann effizient und idiomatisch schreiben? – pathikrit
Ich glaube, der idiomatische Weg wäre, 'scala.util.Try' zu verwenden, um die Funktionsaufrufe einzubinden, aber ich kann Ihnen keinen Beispielcode liefern. –