How can I write f(g(h(x))) in Scala with fewer parentheses?
Expressions like
ls map (_ + 1) sum
are lovely because they are left-to-right and not nested. But if the functions in question are defined outside the class, it is less pretty.
Following an example I tried
final class DoublePlus(val self: Double) {
def hypot(x: Double) = sqrt(self*self + x*x)
}
implicit def doubleToDoublePlus(x: Double) =
new DoublePlus(x)
which w开发者_如何学Corks fine as far as I can tell, other than
A lot of typing for one method
You need to know in advance that you want to use it this way
Is there a trick that will solve those two problems?
You can call andThen
on a function object:
(h andThen g andThen f)(x)
You can't call it on methods directly though, so maybe your h
needs to become (h _)
to transform the method into a partially applied function. The compiler will translate subsequent method names to functions automatically because the andThen
method accepts a Function
parameter.
You could also use the pipe operator |>
to write something like this:
x |> h |> g |> f
Enriching an existing class/interface with an implicit conversion (which is what you did with doubleToDoublePlus
) is all about API design when some classes aren't under your control. I don't recommend to do that lightly just to save a few keystrokes or having a few less parenthesis. So if it's important to be able to type val h = d hypot x
, then the extra keystrokes should not be a concern. (there may be object allocations concerns but that's different).
The title and your example also don't match:
f(g(h(x)))
can be rewritten asf _ compose g _ compose h _ apply x
if your concern is about parenthesis or f compose g compose h apply x
if f, g, h are function objects rather than def.
But ls map (_ + 1) sum
aren't nested calls as you say, so I'm not sure how that relates to the title. And although it's lovely to use, the library/language designers went through a lot of efforts to make it easy to use and under the hood is not simple (much more complex than your hypot example).
def fgh (n: N) = f(g(h(n)))
val m = fgh (n)
Maybe this, observe how a is provided:
def compose[A, B, C](f: B => C, g: A => B): A => C = (a: A) => f(g(a))
basically like the answer above combine the desired functions to a intermediate one which you then can use easily with map.
Starting Scala 2.13
, the standard library provides the chaining operation pipe
which can be used to convert/pipe a value with a function of interest.
Using multiple pipe
s we can thus build a pipeline
which as mentioned in the title of your question, minimizes the number of parentheses:
import scala.util.chaining._
x pipe h pipe g pipe f
精彩评论