定制“出租"Scala 中的表达式 [英] Custom "let" expression in Scala
问题描述
我希望 let
构造类似于 Scala 中的 Haskell 中的构造.我尝试了几种方法,但似乎没有一个是好的.这是一些代码:
I'd love to have let
construct similar to the one in Haskell in Scala. I tried a few ways, but none seems to be good. Here's some 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'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
关键字):
This is the ideal look of it (with only one binding, more could be separated by ,
; not sure about the in
keyword):
// desired look
def letTest(): Int =
let res = heavyCalc() in
if (cond(res)) doSomethingWithRes(res) else 0
我不确定这是否可能,但我没有使用宏等大多数高级 Scala 东西的经验,所以我无法确定.
I'm not sure if it's possible, but I have no experience with most of advanced Scala stuff like macros, so I can't really tell.
明确地说,我对它的主要期望是:表达式和相对简单的语法(如上面概述的那样).>
To be clear, the main things I'm expecting from it are: being expression and relatively simple syntax (like the one outlined above).
推荐答案
您可以使用前向管道:
object ForwardPipeContainer {
implicit class ForwardPipe[A](val value: A) extends AnyVal {
def |>[B](f: A => B): B = f(value)
}
}
像这样使用:
import ForwardPipeContainer._
def f(i: Int) = i * i
println( f(3) |> (x => x * x) )
<小时>
你可以在一个元组中放置多个参数:
You can put multiple arguments in a tuple:
println( (f(2), f(3)) |> (x => x._1 * x._2) )
如果与部分函数 synatx 结合看起来更好:
which looks better if combined with partial function synatx:
println( (f(2), f(3)) |> { case (x, y) => x * y } )
<小时>
此答案是 在 Scala 中重用函数结果的好方法是什么 的变体,两者均基于在单行中缓存一个中间变量,我从那里得到了最初的想法.
This answer is a variation of What is a good way of reusing function result in Scala, and both are based on Cache an intermediate variable in an one-liner where I got the initial idea from.
这篇关于定制“出租"Scala 中的表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!