Scala 中的自定义“let”表达式

2024-04-16

我很想拥有let构造类似于 Scala 中的 Haskell 中的构造。我尝试了几种方法,但似乎都不好。这是一些代码:

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:要明确的是,我期望的主要内容是:表达并且相对地简单的语法(就像上面概述的那样)。


你可以使用前管:

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) )

您可以将多个参数放入一个元组中:

println( (f(2), f(3)) |> (x => x._1 * x._2) )

如果与部分函数语法结合使用,看起来会更好:

println( (f(2), f(3)) |> { case (x, y) => x * y } )

这个答案是一个变体Scala 中重用函数结果的好方法是什么 https://stackoverflow.com/a/17470016/2390083,并且两者都基于在一行中缓存一个中间变量 https://stackoverflow.com/a/15957059/2390083我最初的想法是从哪里得到的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 中的自定义“let”表达式 的相关文章

随机推荐