-
-
Save kjetilv/434620 to your computer and use it in GitHub Desktop.
// A simple trait: | |
trait CascadingActions { | |
implicit def tToActioneerT[T](t: T) = Actioneer(t) | |
case class Actioneer[T](tee: T) { | |
def withAction(action: (T => Unit)): T = | |
withActions(action) | |
def withActions(actions: (T => Unit)*): T = { | |
actions foreach (_ (tee)) | |
tee | |
} | |
} | |
} | |
// Yet with nice properties when you're dealing with | |
// an object that take a lot of setters, and you really | |
// wish it supported cascading: | |
def newStupid = { | |
val stupidTemporaryVariable = new StupidObject | |
stupidTemporaryVariable setSillyProperty "foo" | |
stupidTemporaryVariable setAnotherOne "bar" | |
stupidTemporaryVariable // mention it AGAIN here, just so it gets returned | |
} | |
// But instead: | |
def newStupid = new StupidObject withActions( | |
_ setSillyProperty "foo", | |
_ setAnotherOne "bar") | |
// Wow! |
Hmmm... did you try that? I typed in the following:
class StupidObject {
setFoo {
println("Foo")
}
}
val nso = new StupidObject {
import nso._
setFoo
}
println(nso)
However, this made the compiler complain: illegal cyclic reference involving value
Removing the import fixes it, because what you are really doing is creating a subclass, right? But that fails if it's final. The compiler complains: illegal inheritance from final class StupidObject
I was a bit puzzled at first, because I couldn't see how the reference could be set to itself before it, well, imported itself. I may simply be confused, of course. Did you make it work?
def returning[T](x: T)(f: T => Unit): T = { f(x) ; x }
returning(new StupidObject)(x => { x setSillyProperty "foo" ; x setAnotherOne "bar" })
er, I meant:
class StupidObject {
var sillyProperty: String = _
var anotherOne: String = _
}
val nso = new StupidObject;
{
import nso._
sillyProperty = "foo"
anotherOne = "bar"
}
That works too, although I think you mean
def returning[T](x: T)(f: T => Unit) = { f(x); x }
and for extra credit:
def returning[T](x: T)(fs: (T => Unit)*) = { fs foreach (_(x)); x }
or something.
@retronym: yes, that avoids the issue with StupidObject being final, and it doesn't introduce a new subclass. However, it is no longer a single expression, but is back to being a sequence of statements, the last one being the expression returned:
def newStupid {
val nso = new StupidObject;
{
import nso._
sillyProperty = "foo"
anotherOne = "bar"
}
nso // ... and an expression at the end
}
re "although I think you mean..." I meant exactly what I wrote; unfortunately the helpful markup processor betrayed me. If you look at the raw text you will see the untainted vision.
Cute hack, but this is almost as easy and a little more direct: