Use the extend-my-library pattern:
implicit class SideEffectPassthrough[A](val a: A) extends AnyVal {
def se(sideEffectFunction: A => Unit): A = {
sideEffectFunction(a)
a
}
}
def compute(a: Int) = a + 2 + 3
val x = compute(1).se(println)
// x: Int = 6
The compiler will do the wrapping for you, making the syntax cleaner. (However, note that when we add extends AnyVal
, we are actually ensuring that the compiler will rewrite this code so that it doesn't literally do any wrapping; instead it will create a static function to handle the behavior, which means less runtime overhead since no wrapper object will need to be instantiated.)
The sideEffectFunction
argument of se
can be any arbitrary function, as long as it takes as it's argument the result of the preceding expression:
val y = compute(1).se { r =>
println("Performing a side effect now!")
println(r)
}
// y: Int = 6
Just for the sake of completeness, here is a different way to accomplish the same goal:
def printAndReturn[A](block: => A): A = {
val result = block
println(result)
result
}
val x = printAndReturn(1+2+3)
// x: Int = 6
val y = printAndReturn {
val a = 1 + 2
a + 3
}
// y: Int = 6
The argument block
can be any arbitrary expression, including any arbitrary block of code. Notice that it is passed by name, so it is evaluated inside se
.