I want to know if it's possible to define a pipeline operator like %>%
in magrittr
package of R
language. I found several similar implementations that look like:
implicit class PipelineContainer[F](val value: F) {
def |>[G] (f: F => G) = f(value)
}
so that x |> f |> g
works like g(f(x))
Now I want this operator works even when functions takes more than 1 parameter, in this case value on left side of pipeline parameter becomes the first parameter of function on the right side. For example, x |> f(2) |> g(3)
becomes g(f(x, 2), 3)
. How can I implement this in scala? It doesn't have to be the same syntax as I show here, but the simpler the better.
There are a few options.
One is to just create the functions inline. It's only slightly messy.
x |> (z=>f(z,2)) |> (z=>g(z,3))
Another is to create shortcut methods that can collapse the arity of an existing function. In general it's a lot of boilerplate, but the first one is easy enough:
implicit class RichPipes[Y](y: Y) {
def |>[Z](f: Y => Z) = f(y)
def &>[X, Z](f: (X, Y) => Z): (X => Z) = (x: X) => f(x, y)
}
Then you can inject the other arguments inline (taking advantage of the fact that &
is higher precedence than |
):
x |> 2 &> f |> 3 &> g
Personally, I find this style confusing, but the compiler's fine with it.
Another option is to convert the methods to functions to start with (if necessary) and then enrich those functions to have a partial application helper method:
implicit class RichFunction2[A,B,Z](f: (A,B) => Z) {
def %(b: B): (A => Z) = (a: A) => f(a,b)
}
Now you can
x |> f _ % 2 |> g _ % 3
Finally, if you happen to be able to write the functions differently, you can make it work without any extra machinery save a trailing _
to let the compiler know what you're up to; the difference is just that the application goes through the last of multiple parameter blocks:
def h(y: Int)(x: Int) = x + y
def i(y: Int)(x: Int) = x * y
x |> h(2) _ |> i(3) _
As a final thought, though, injecting parameters mid-stream may not be the easiest thing to follow for the uninitiated. You might consider whether it's good programming practice as opposed to adopting a different workflow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With