J'aimerais construire let
semblable à celui de Haskell dans Scala. J'ai essayé quelques moyens, mais aucun ne semble être bon. Voici un code:Expression "let" personnalisée dans Scala
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's 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()
}
}
)
}
Ceci est le look idéal de celui-ci (avec une seule liaison, plus pourrait être séparés par ,
, pas sûr du mot-clé in
):
// desired look
def letTest(): Int =
let res = heavyCalc() in
if (cond(res)) doSomethingWithRes(res) else 0
Je ne suis pas Bien sûr, si c'est possible, mais je n'ai aucune expérience avec la plupart des trucs Scala avancés comme les macros, donc je ne peux pas vraiment le dire.
EDIT1: Pour être clair, les principales choses que je prévois de lui sont les suivants: être expression et relativement syntaxe simple (comme celui décrit ci-dessus).
Pour ceux d'entre nous qui ne parlent pas Haskell, pourriez-vous expliquer ce que "let" est censé faire? –
Le 'letWithVal' fait la même chose que le' let' dans le 'letTest'. – monnef