在基本数组

时间:2016-10-28 06:45:05

标签: scala error-handling

val myArray = Array("1", "2")
val error = myArray(5)//throws an ArrayOutOfBoundsException

myArray没有固定的大小,这就解释了为什么可能会在上面的第二行执行调用。

首先,我从未真正理解将error handling用于预期错误的原因。我认为这种做法是不好的,因为编码技巧不好或倾向于懒惰,我是错误的吗?

处理上述情况的最佳方法是什么?

  • 我倾向于:防止访问所描述数据的基本实施(条件);
  • 使用Option;
  • 使用TryEither;
  • 使用try-catch块。

3 个答案:

答案 0 :(得分:1)

使用arr.lift(标准库中提供)返回Option而不是抛出异常。

如果不使用safely

尝试访问元素safely,以避免在代码中间意外抛出异常。

implicit class ArrUtils[T](arr: Array[T]) {
   import scala.util.Try
   def safely(index: Int): Option[T] = Try(arr(index)).toOption
}

用法:

arr.safely(4)

<强> REPL

scala> val arr = Array(1, 2, 3)
arr: Array[Int] = Array(1, 2, 3)

scala> implicit class ArrUtils[T](arr: Array[T]) {
   import scala.util.Try
   def safely(index: Int): Option[T] = Try(arr(index)).toOption
  }
defined class ArrUtils

scala> arr.safely(4)
res5: Option[Int] = None

scala> arr.safely(1)
res6: Option[Int] = Some(2)

答案 1 :(得分:1)

如果索引myArray有时会出错,那么听起来Option就好了。

myArray.lift(1)  // Option[String] = Some(2)
myArray.lift(5)  // Option[String] = None

您可以使用Try(),但如果您已经知道错误是什么并且您对捕获或报告它不感兴趣,为什么还要费心呢?

答案 2 :(得分:1)

1避免通过索引

寻址元素

Scala提供了一组丰富的集合操作,这些操作通过ArrayOps隐式转换应用于阵列。这样,我们就可以在数组上使用combinators,例如mapflatMaptakedrop,....而不是按索引寻址元素。

2防止访问超出范围

我在解析类似CSV的数据时经常看到的一个例子(在Spark中):

case class Record(id:String, name: String, address:String)
val RecordSize = 3
val csvData = // some comma separated data
val records = csvData.map(line => line.split(","))
                     .collect{case arr if (arr.size == RecordSize) => 
                              Record(arr(0), arr(1), arr(2))}

3使用适合当前上下文的检查

如果我们使用monadic构造来组合对某些资源的访问,请对应用程序流使用适合的提升错误方式: 例如想象一下,我们正在从某个存储库中检索用户首选项,我们想要第一个:

def getUserById(id:ID):Option[User]
def getPreferences(user:User) : Option[Array[Preferences]]

val topPreference = for {
      user <- userById(id)
      preferences <- getPreferences(user)
      topPreference <- preferences.lift(0)
   } yield topPreference

(甚至更好,应用建议#1):

val topPreference = for {
      user <- userById(id)
      preferences <- getPreferences(user)
      topPreference <- preferences.headOption
   } yield topPreference

尝试

def getUserById(id:ID): Try[User]
def getPreferences(user:User) : Try[Array[Preferences]]
val topPreference = for {
      user <- userById(id)
      preferences <- getPreferences(user)
      topPreference <- Try(preferences(0))
   } yield topPreference

作为一般指导:使用principle of least power。 如果可能,请使用无错误的组合器:= array.drop(4).take(1) 如果重要的是有元素,请使用Option 如果我们需要保留找不到元素的原因,请使用Try

让节目的类型和背景指导您。