Skip to content

Instantly share code, notes, and snippets.

@AGhost-7
Created May 1, 2015 01:06
Show Gist options
  • Save AGhost-7/701b30de83a6190c9538 to your computer and use it in GitHub Desktop.
Save AGhost-7/701b30de83a6190c9538 to your computer and use it in GitHub Desktop.
Function Piping
import sbt._
import Keys._
import java.io.File
object FunBuild extends Build {
lazy val root = Project(id = "root", base = file(".")).settings(
name := "Fun",
version := "0.1",
scalaVersion := "2.11.6",
commands += mkFun
)
val br = IO.Newline
val mkFun = Command.command("mk-fun") { state =>
IO.append(ckFile,
s"""package aghost7.fun
|object Fun {
|$br${mkPipe}$br
|}""".stripMargin)
state
}
def ckFile = {
val fl = new File("src/main/scala/fun.scala")
if(fl.exists())
IO.delete(fl)
IO.touch(fl)
fl
}
def mkPipe = {
def pipeMethod(n: Int) = {
val base = "\tdef pipe[" +
(0 until n).map { i => ('A' + i).toChar }.mkString(", ") +
"](a: A, " +
(0 until n - 1).map { i =>
s"f${i + 1}: ${('A' + i).toChar} => " + ('B' + i).toChar
}.mkString(", ") +
s"): ${('A' + n - 1).toChar} = $br\t\t"
def funcGen(i: Int): String = {
if(i == 1) "f1(a)"
else s"f$i(${funcGen(i - 1)})"
}
base + funcGen(n - 1)
}
(3 to 22).map(pipeMethod).mkString(br)
}
}
package aghost7.fun
object Fun {
def pipe[A, B, C](a: A, f1: A => B, f2: B => C): C =
f2(f1(a))
def pipe[A, B, C, D](a: A, f1: A => B, f2: B => C, f3: C => D): D =
f3(f2(f1(a)))
def pipe[A, B, C, D, E](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E): E =
f4(f3(f2(f1(a))))
def pipe[A, B, C, D, E, F](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F): F =
f5(f4(f3(f2(f1(a)))))
def pipe[A, B, C, D, E, F, G](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G): G =
f6(f5(f4(f3(f2(f1(a))))))
def pipe[A, B, C, D, E, F, G, H](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H): H =
f7(f6(f5(f4(f3(f2(f1(a)))))))
def pipe[A, B, C, D, E, F, G, H, I](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I): I =
f8(f7(f6(f5(f4(f3(f2(f1(a))))))))
def pipe[A, B, C, D, E, F, G, H, I, J](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J): J =
f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K): K =
f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L): L =
f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M): M =
f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N): N =
f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O): O =
f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P): P =
f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q): Q =
f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q, f17: Q => R): R =
f17(f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q, f17: Q => R, f18: R => S): S =
f18(f17(f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q, f17: Q => R, f18: R => S, f19: S => T): T =
f19(f18(f17(f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q, f17: Q => R, f18: R => S, f19: S => T, f20: T => U): U =
f20(f19(f18(f17(f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a))))))))))))))))))))
def pipe[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V](a: A, f1: A => B, f2: B => C, f3: C => D, f4: D => E, f5: E => F, f6: F => G, f7: G => H, f8: H => I, f9: I => J, f10: J => K, f11: K => L, f12: L => M, f13: M => N, f14: N => O, f15: O => P, f16: P => Q, f17: Q => R, f18: R => S, f19: S => T, f20: T => U, f21: U => V): V =
f21(f20(f19(f18(f17(f16(f15(f14(f13(f12(f11(f10(f9(f8(f7(f6(f5(f4(f3(f2(f1(a)))))))))))))))))))))
}

I was looking for a solution to a recurring pattern in my use of the Play Framework. Often I'd find myself in the situation where I'd be stuck with something along the lines of:

Future.successful(BadRequest(views.html.login(errorMsg)))

For obvious reasons, this isn't quite readable. You can break down the calls like so...

val res = BadRequest(views.html.login(errorMsg))
Future.successful(res)

But now the code is more verbose. I remembered a little pattern in Javascript where you can pipe into each function with a starting value. Its a bit trickier in Scala since the language is statically typed, but you can still make it work. Just had to generate the code :)

import aghost7.fun.Fun._
def capitalize(name: String) = name.toUpperCase
def reverse(str: String) = str.reverse
def greet(name: String) = println("hello! " + name)
val result: Unit = pipe("mathieu", capitalize, reverse, { name: String => println(s"Hello $name")} )

Now my code can look like so:

pipe(errorMsg, views.html.login, BadRequest, Future.successful)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment