Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <a href="https://stackoverflow.com/a/20181011/1017211" title="answer">answer</a> from Akos Krivachy is pretty close, but since I can't append my complete solution to it I have to create a new separate answer (this feature of SO seems a bit weird to me).</p> <pre><code>object ApplyTroubles2 extends App { import GrepOption.GrepOption abstract class Builder { var parent: Builder = null def getOutput: String def append(ch: Builder) = { ch.parent = this; ch } def echo(s: String) = append(new Echo(s)) def wc() = append(new Wc()) def grep(s: String, opts: Set[GrepOption]) = append(new Grep(s, opts)) def grep(s: String) = append(new Grep(s)) } object MainBuilder extends Builder { def getOutput: String = "" override def append(ch: Builder): Builder = ch } class Echo(data: String) extends Builder { def getOutput = data } class Wc() extends Builder { def getOutput = parent.getOutput.size.toString } class Grep(var pattern: String, options: Set[GrepOption]) extends Builder { def this(pattern: String) = this(pattern, Set.empty) val isCaseInsensitive = options.contains(GrepOption.CASE_INSENSITIVE) if (isCaseInsensitive) pattern = pattern.toLowerCase def getOutput = { val input = if (isCaseInsensitive) parent.getOutput.toLowerCase else parent.getOutput if (input.contains(pattern)) input else "" } } object GrepOption extends Enumeration { type GrepOption = Value val CASE_INSENSITIVE = Value } // all above is un-touchable (e.g. code of a library I want to pimp out) // all bellow are the pimps I wanted // ( // based on this answer [https://stackoverflow.com/a/20181011/1017211] // from Akos Krivachy [https://stackoverflow.com/users/1697985/akos-krivachy] // ) object MyBuilder { type MyBuilderTransformer = MyBuilder =&gt; MyBuilder def builderFunc(func: Builder =&gt; Builder): MyBuilderTransformer = (x: MyBuilder) =&gt; {func(x.builder).wrap} // methods in original library without parameters can be represented as vals val wc: MyBuilderTransformer = builderFunc(_.wc()) // when it has parameters it must be def, we need to pack params def grep(s: String): MyBuilderTransformer = builderFunc(_.grep(s)) def grep(s: String, ss: Set[GrepOption]): MyBuilderTransformer = builderFunc(_.grep(s, ss)) // root expression, differs a bit from original, but in this case it's good enough def fromString(msg: String): MyBuilder = MyBuilder(MainBuilder.echo(msg)) } // wrapper class case class MyBuilder(builder: Builder) implicit class BuilderPimps(b: Builder) { def wrap = MyBuilder(b) } implicit class MyBuilderPimps(b: MyBuilder) { def |(fn: MyBuilder =&gt; MyBuilder): MyBuilder = fn(b) def getStringOutput: String = b.builder.getOutput def &gt;&gt; : String = getStringOutput } // this all works (shows how an end user would use this pimps) import MyBuilder._ println(fromString("abc") | wc getStringOutput) println(fromString("abc") | wc &gt;&gt;) println(fromString("abc") | grep("b") | wc getStringOutput) println(fromString("abc") | grep("b") | wc &gt;&gt;) println(fromString("abc") | grep("B", Set(GrepOption.CASE_INSENSITIVE)) | wc getStringOutput) println(fromString("abc") | grep("B", Set(GrepOption.CASE_INSENSITIVE)) | wc &gt;&gt;) println(fromString("abc") | grep("y", Set(GrepOption.CASE_INSENSITIVE)) | wc getStringOutput) println(fromString("abc") | grep("y", Set(GrepOption.CASE_INSENSITIVE)) | wc &gt;&gt;) } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload