#scala #performance #coding-style #try-catch #code-cleanup
#scala #Производительность #стиль кодирования #попробуйте-поймайте #очистка кода
Вопрос:
Я прочитал о методе transform в Try и сравнил этот метод с другими методами, чтобы выяснить, какой из них будет более понятным для кодирования. Я показываю вам приведенный ниже код
val value: Try[Int] = Try("1".toInt)
.transform(f => Success(f), e => Success(0))
val value2: Try[Int] = Try("1".toInt) match {
case Success(f) => Success(f)
case Failure(e) => Success(0)
}
val value3: Try[Int] = Try("1".toInt)
.map(f => f)
.recover {
case e: Exception => 0
}
Я хотел бы знать, какой из них будет лучше в этих случаях и по какой причине?
Спасибо
Ответ №1:
Если вы хотите восстановиться после любого (не фатального) исключения, имеет больше смысла, чтобы результат был Int
чем Try[Int]
, поскольку вы знаете, что у вас есть значение success , поэтому наиболее идиоматичное решение будет выглядеть следующим образом:
scala> import scala.util.Try
import scala.util.Try
scala> val value4: Int = Try("1".toInt).getOrElse(0)
value4: Int = 1
Если ваша фактическая логика более сложная или вы просто предпочитаете быть действительно явной, вы могли бы сопоставить шаблон:
scala> import scala.util.{ Failure, Success, Try }
import scala.util.{Failure, Success, Try}
scala> val value5: Int = Try("1".toInt) match {
| case Success(i) => i
| case Failure(_) => 0
| }
value5: Int = 1
Если по какой-то причине вы действительно хотите получить a Try[Int]
, даже если вы знаете, что это всегда будет a Success
, я бы предложил использовать recover
и NonFatal
:
scala> import scala.util.Try, scala.util.control.NonFatal
import scala.util.Try
import scala.util.control.NonFatal
scala> val value5: Try[Int] = Try("1".toInt).recover {
| case NonFatal(_) => 0
| }
value5: scala.util.Try[Int] = Success(1)
Обратите внимание, что это исключает ненужное .map(f => f)
из вашего value3
, а также заменяет catch-all case e: Exception
на NonFatal
extractor от Scala, который не будет соответствовать таким фатальным исключениям, как OutOfMemoryError
(обычно вы не можете восстановиться из этих исключений, поэтому вы не хотите их перехватывать здесь).
Однако даже в этом случае его использование не было бы идиоматичным transform
, поскольку вы можете выразить операцию с помощью менее мощного комбинатора ( recover
), и вы всегда должны предпочесть самое простое решение, которое делает то, что вам нужно.
На самом деле здесь нет никаких причин возвращать a Try[Int]
, поэтому я бы просто выбрал getOrElse
.