Scalaで、パイプライン演算子 pipeline operator

Scalaで、F#のパイプライン演算子のようなものをつくりたい。

とりあえずIntで書いてみたけどうまくいかないな。パイプのたびに()が入れ子になるのがじゃまだ。どうすればよいのだろう。うーん。再帰的な、なにかなんだろうか。

scala> val f = (x: Int) => 2 * x
f: (Int) => Int = <function1>

scala> val g = (x: Int) => x + 1
g: (Int) => Int = <function1>

scala> val h = (x: Int) => x * x
h: (Int) => Int = <function1>

scala> class IntPipe (val f: Function[Int, Int]) {
     | def |>: (x: Int) = f.apply(x)
     | }
defined class IntPipe

scala> implicit def IntFuncPipe(f: Function[Int, Int]) = new IntPipe(f)
IntFuncPipe: (f: (Int) => Int)IntPipe

scala> 1 |>: f
res18: Int = 2

scala> 1 |>: f |>: g
<console>:15: error: type mismatch;
 found   : (Int) => Int
 required: Int
       1 |>: f |>: g
               ^

scala> (1 |>: f) |>: g
res21: Int = 3

scala> ((1 |>: f) |>: g) |>: h
res22: Int = 9

scala>

以下のようになるようにしたいんだよな

scala> 1 |>: f |>: g |>: h
res23: Int = 9

したはちがう。

scala> (f andThen g andThen h)(1)
res23: Int = 9
scala> 1 |>: ( f andThen g andThen h)
res24: Int = 9

どうしたもんだか

あらためて、、、、

scala> val f = (x: Int) => 2 * x
f: (Int) => Int = <function1>

scala> val g = (x: Int) => x + 1
g: (Int) => Int = <function1>

scala> val h = (x: Int) => x * x
h: (Int) => Int = <function1>

scala> class IntPipe(x: Int) {
     |     def |> (f: Function[Int, Int]) = f.apply(x)
     | }
defined class IntPipe

scala> implicit def intToIntPipe(x: Int) = new IntPipe(x)
intToIntPipe: (x: Int)IntPipe

scala>  1 |> f
res0: Int = 2

scala>  1 |> f |> g
res1: Int = 3

scala>  1 |> f |> g |> h
res2: Int = 9

おおー、うまくいった!はじめに、:があたまをよぎって、それがあたまから離れなかったのがまずかった。

でもこれだと、いちいち、implicit defが必要で、めんどうくさくて、つかいものにならないな。

さらに、あらためて、

scala> val f = (x: Int) => 2 * x
f: (Int) => Int = <function1>

scala> val g = (x: Int) => x + 1
g: (Int) => Int = <function1>

scala> val h = (x: Int) => x * x
h: (Int) => Int = <function1>

scala> class Pipe[A](x: A) {
     |     def |> [B](f: Function[A, B]) = f.apply(x)
     | }
defined class Pipe

scala> implicit def objectToPipe[A](x: A) = new Pipe(x)
objectToPipe: [A](x: A)Pipe[A]

scala>  1 |> f
res0: Int = 2

scala>  1 |> f |> g
res1: Int = 3

scala>  1 |> f |> g |> h
res2: Int = 9

これで、はじめの期待通り!