Option包装值是一个好的模式吗?

lee*_*777 11 scala

我最近写了以下Scala:

val f: File = ... // pretend this file came from somewhere
val foo = toFoo(io.Source.fromFile(f).mkString)
Run Code Online (Sandbox Code Playgroud)

我真的不喜欢这种流动的方式.要了解发生了什么,你必须从f中间开始,向左fromFile阅读,向右mkString阅读,再向左阅读toFoo.啊.

特别是在习惯了序列的功能转换之后,这很难理解.我的下一次尝试看起来像这样:

val foo = Some(f)
  .map(io.Source.fromFile)
  .map(_.mkString)
  .map(toFoo)
  .get
Run Code Online (Sandbox Code Playgroud)

我喜欢这个更好的流程.你可以看到会发生什么这是一个很好的使用Option课程?还是我在滥用它?有没有更好的模式可以用来实现相同的流程?

Rex*_*err 27

这完全没问题.然而,有一种方法|>Scalaz,做一个更好的,你可以自己创建它,如果你不希望所有Scalaz的:

class Piper[A](a: A) { def |>[B](f: A => B) = f(a) }
implicit def pipe_everything[A](a: A) = new Piper(a)

f |> io.Source.fromFile |> {_.mkString} |> toFoo
Run Code Online (Sandbox Code Playgroud)

就个人而言,我倾向于编写大量需要括号的代码,而且在大多数情况下我喜欢比运算符更好的方法,所以在我的代码中我通常称之为|>"use",但这是相同的交易:

f.use(io.Source.fromFile).use(_.mkString).use(toFoo)
Run Code Online (Sandbox Code Playgroud)

在Scala 2.11或更高版本中,您可以使用(略微)较少的语法获得相同的行为和改进的性能:

implicit class Piper[A](private val a: A) extends AnyVal {
  def |>[B](f: A => B) = f(a)
}
Run Code Online (Sandbox Code Playgroud)


Wil*_*ger 5

我对这里给出的其他答案没有任何问题,但您是否考虑将toFoo的名称更改为"流动"更好的内容?我的意思是,toFoo真的闻起来应该在表达式的右边,但是如果你把它重命名为其他东西,它也可能适合左边.

// toFoo, as defined by you
val foo = toFoo(io.Source.fromFile(f).mkString)
// Same function, different name
val foo = createFooFrom(io.Source.fromFile(f).mkString)
Run Code Online (Sandbox Code Playgroud)