0

I am looking for something in scala to write the following code in a more compact way:

def getSomething():X = {
  val result = compute(...)
  println(result)
  result
}

I am thinking of something like that:

def getSomething():X = {
  MagicWrapper(compute(...)).do(println)
}

so that do is executed but the original value is returned. sounds like such a thing should exist somewhere but I could not found anything.

wrm
  • 1,898
  • 13
  • 24

1 Answers1

3

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.

dhg
  • 52,383
  • 8
  • 123
  • 144