Я бы с удовольствием построил let
, подобный тому, который был в Haskell в Scala. Я пробовал несколько способов, но никто не кажется хорошим. Вот код:Пользовательское выражение «let» в 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()
}
}
)
}
Это идеальный вид из него (только с одним связыванием, еще может быть отделена от ,
, не уверен в in
ключевое слово):
// desired look
def letTest(): Int =
let res = heavyCalc() in
if (cond(res)) doSomethingWithRes(res) else 0
Я не конечно, если это возможно, но у меня нет опыта работы с большинством продвинутых материалов Scala, таких как макросы, поэтому я не могу сказать.
EDIT1: Для того, чтобы быть ясно, что основные вещи, я ожидаю от него являются: быть выражение и относительно простой синтаксис (как один, описанной выше).
Для тех из нас, кто не говорит Haskell, не могли бы вы объяснить, что «пусть» должно делать? –
'letWithVal' делает то же самое, что и' let' в 'letTest'. – monnef