在scala中,将一系列组合函数应用于值的惯用方法是什么?

时间:2013-12-13 19:27:24

标签: scala idioms

编写以下内容的惯用方法是什么?

val starting_value = ...
val result1 = f1(startingValue)
val result2 = f2(result1)
...
val resultN = fN(resultN-1)

如果starting_value是我想要应用这些功能的项目列表,我可以写

starting_list.map(f1).map(f2)...map(fN)

我可以通过做

这样的事来伪造这个
Some(starting_value).map(f1)....map(fN).get

List(starting_value).map(f1)....map(fN).head

但这似乎不必要地混淆。

注意:This question似乎有关,但似乎是关于下游问题。

4 个答案:

答案 0 :(得分:10)

(f1 andThen f2 andThen ... fN) {
  startingValue
}

答案 1 :(得分:4)

使用正向管道运算符。例如(对于def f(s: String) = s.length):

scala> "abc" |> f |> 0.until
res16: scala.collection.immutable.Range = Range(0, 1, 2)

您可以在Scalaz中找到它,但您也可以找到它的定义elsewhere

答案 2 :(得分:2)

您可以定义一个也是value class的扩展类。值类是一种特殊的Scala构造,它在新的编译时类型中包含单个值,但是包含相同的运行时对象,从而避免任何新的内存分配。该课程看起来像:

implicit class Piper[A](val x: A) extends AnyVal {
  def |>[B](f: A => B) = f(x)
}

现在你做的时候:

startingValue |> f1 |> f2 |> ... |> fN

Scala在编译时隐式包装Piper对象中的起始值和每个中间值,并应用Piper对象的|>方法,将中间值向前传递。在运行时不会产生额外的内存或时间成本。

通过/u/Baccata64

答案 3 :(得分:-1)

您还可以考虑将值包装到Try中,然后在其上应用map(fN)。然后您将证明,如果任何函数失败,您将不会得到意外的异常。然后,您可以匹配成功/失败并进行一些恢复或仅打印确切的故障。