(f1 andThen f2 andThen ... fN) {
startingValue
}
In scala, what's the idiomatic way to apply a series of composed functions to a value?
Pregunta
What's the more idiomatic way to write the following?
val starting_value = ...
val result1 = f1(startingValue)
val result2 = f2(result1)
...
val resultN = fN(resultN-1)
If starting_value
were a list of items to which I wanted to apply these functions, I could write
starting_list.map(f1).map(f2)...map(fN)
I can fake this by doing something like
Some(starting_value).map(f1)....map(fN).get
or
List(starting_value).map(f1)....map(fN).head
but this seems unnecessarily confusing.
Note: This question seems related but seems to be about a downstream issue.
Solución
Otros consejos
Use the forward pipe operator. For example (for def f(s: String) = s.length
):
scala> "abc" |> f |> 0.until
res16: scala.collection.immutable.Range = Range(0, 1, 2)
You can find it in Scalaz, but you can find its definition elsewhere as well.
You can define an extension class that is also a value class. A value class is a special Scala construct that wraps up a single value inside a new compile-time type but the same exact runtime object, thus avoiding any new memory allocation. The class would look like:
implicit class Piper[A](val x: A) extends AnyVal {
def |>[B](f: A => B) = f(x)
}
Now when you do:
startingValue |> f1 |> f2 |> ... |> fN
Scala implicitly wraps up the starting value and each intermediate value in a Piper
object at compile time and applies the Piper
object's |>
method, passing the intermediate values forward. At runtime no extra memory or time costs are incurred.
via /u/Baccata64
You could as well consider wrapping you value into Try, and then applying map(fN) on it. Then you will have prove, that if any function will fail, you won't get unexpected exception. You can then match on Success/Failure and do some recovery or just printing exact failure.