带有选项的scala编程实践

scala programming practice with option

可能是我的设计有缺陷(很可能是),但我一直在思考 OptionScala 中的使用方式,对此我不是很满意。假设我有 3 种方法可以这样互相调用:

def A(): reads a file and returns something
def B(): returns something
def C(): Side effect (writes into DB)

C() 调用 B(),然后 B() 调用 A()

现在,由于 A() 依赖于 I/O 操作,我必须处理异常以及 return 和 Option 否则它不会编译(如果 A() 没有 return 任何东西)。由于 B()A() 接收到一个 Option 并且它必须 return 一些东西,它被绑定到 return 另一个 OptionC().因此,您可以想象我的代码充满了 match/case Some/case None(不要总是使用 getOrElse())。而且,如果 C() 依赖于其他一些方法,这些方法也 return Option,你会害怕查看 C() 的定义。

那么,我是不是漏掉了什么?或者我的设计有多大缺陷?我该如何改进它?

在类型 Option 上使用 match/case 通常在您想要丢弃 Option 并在处理 [=15= 之后产生一些值时很有用] 但如果您有 None,则为同一类型的不同值。 (就个人而言,我通常发现 fold 对于这种情况更干净。)

另一方面,如果您要传递 Option,那么还有其他方法可以解决。

def a():Option[DataType] = {/*read new data or fail*/}

def b(): Optioon[DataType] = {
  ... //some setup
  a().map{ inData =>
    ... //inData is real, process it for output
  }
}
def c():Unit = {
  ... //some setup
  b().foreach{ outData =>
    ... //outData is real, write it to DB
  }
}

am I missing something?

Option 是一个设计决定,但可以有其他设计决定。即当您想描述由 API 编辑的错误 return 时会发生什么? Option只能告诉你两种状态,要么我成功读取了一个值,要么我失败了。但有时你真的很想知道 为什么 你失败了。或者更多,如果我 return None,是因为文件不存在还是因为我因异常而失败(即我没有读取文件的权限?)。

无论您选择哪条道路,您通常都会处理一个或多个影响Option 就是这样一种效果,它表示部分函数,​​即此操作可能不会产生结果。正如其他人所说,虽然使用 Option 的模式匹配是一种处理它的方法,但还有其他操作可以减少冗长。

例如,如果您想在值存在的情况下调用一个操作,在值不存在的情况下调用另一个操作,并且它们都具有相同的 return 类型,您可以使用 Option.fold

scala> val maybeValue = Some(1)
maybeValue: Some[Int] = Some(1)

scala> maybeValue.fold(0)(x => x + 1)
res0: Int = 2

一般有many such combinators defined on Option等效果,一开始可能觉得笨重,后来逐渐深入人心,当你想一个接一个地组合操作时,你就会看到它们的真正威力.