I would like to have a let construct similar to the one in Haskell in Scala. I tried several ways, but no one seems good. Here is the code:
object CustomLet extends App { val data = for (i <- 1 to 1024; j <- 1 to 512) yield (i % j) * i * (i + 1) - 1 def heavyCalc() = { println("heavyCalc called"); data.sum } def doSomethingWithRes(res: Int) = { println(s"${res * res}") 1 } def cond(value: Int): Boolean = value > 256 // not really usable, even though it an expression (2x heavyCalc calls) def withoutLet() = if (cond(heavyCalc())) doSomethingWithRes(heavyCalc()) else 0 // not an expression def letWithVal(): Int = { val res = heavyCalc() if (cond(res)) doSomethingWithRes(res) else 0 } // a lot of code to simulate "let", at least it is an expression def letWithMatch(): Int = heavyCalc() match { case res => if (cond(res)) doSomethingWithRes(res) else 0 } // not perfect solution from // http://stackoverflow.com/questions/3241101/with-statement-equivalent-for-scala/3241249#3241249 def let[A, B](param: A)(body: A => B): B = body(param) // not bad, but I'm not sure if it could handle more bindings at once def letWithApp(): Int = let(heavyCalc()) {res => if (cond(res)) doSomethingWithRes(res) else 0} List[(String, () => Int)]( ("withoutLet", withoutLet), ("letWithVal", letWithVal), ("letWithMatch", letWithMatch), ("letWithApp", letWithApp) ).foreach( item => item match { case (title, func) => { println(s"executing $title") val ret = func() println(s"$title finished with $ret") println() } } ) }
This is an ideal view (with a single binding, more can be separated,, not sure about the in keyword):
// desired look def letTest(): Int = let res = heavyCalc() in if (cond(res)) doSomethingWithRes(res) else 0
I'm not sure if this is possible, but I have no experience with most of Scala's advanced stuff, such as macros, so I can't say.
EDIT1: To be clear, the main things that I expect from him are expression and relatively simple syntax (like the one described above).
source share