Let\'s say I have a class and I want to make its methods chainable, I could do something like this:
class MyClass {
def methodOne(arg1: Any): MyClass = {
Leaving aside the question of how wise this is in the first place, it's pretty easy to implement in a type-safe and boilerplate-free way with Shapeless:
import shapeless._
trait ChainableUtils {
def makeChainable[F, Args <: HList](f: F)(implicit
in: FnHListerAux[F, Args => Unit],
out: FnUnHLister[Args => this.type]
) = out((a: Args) => { in(f)(a); this })
}
And then:
scala> class MyClass extends ChainableUtils {
| def func1 = makeChainable((i: Int) => println("Doing stuff."))
| def func2 = makeChainable((a: Any, b: Any) =>
| println("Doing other stuff."))
| }
defined class MyClass
scala> val myInstance = new MyClass
myInstance: MyClass = MyClass@6c86b570
scala> myInstance.func1(1).func2('a, "a").func1(42)
Doing stuff.
Doing other stuff.
Doing stuff.
res0: myInstance.type = MyClass@6c86b570
This will work for any FunctionN
.