Scala中的'let...in'表达式

8
在OCaml中,let...in表达式允许您在表达式中创建一个命名的局部变量,而不是语句。 (是的,我知道实际上一切都是表达式,但是Unit返回值相当无用。)以下是OCaml中的一个快速示例:
let square_the_sum a b = (* function definition *)
    let sum = a + b in (* declare a named local called sum *)
        sum * sum (* return the value of this expression *)

这是我希望看到的Scala代码:
def squareTheSum(a: Int, b: Int): Int =
    let sum: Int = a + b in
        sum * sum

有没有在Scala中可以用来实现这个的东西?
1个回答

14

编辑:

每天都会学到新的东西,而这个问题之前已经被回答过了

object ForwardPipeContainer {
  implicit class ForwardPipe[A](val value: A) extends AnyVal {
    def |>[B](f: A => B): B = f(value)
  }
}

import ForwardPipeContainer._

def squareTheSum(a: Int, b: Int): Int = { a + b } |> { sum => sum * sum }

但我认为这样不太容易阅读,而且不够灵活(如果嵌套的话会很尴尬)。


您可以在def中嵌套valdef。没有特殊的语法;您不需要使用let

def squareTheSum(a: Int, b: Int): Int = {
  val sum = a + b
  sum * sum
}

我认为这里的可读性没有任何不同。但是如果你只想在表达式内创建变量,你仍然可以使用大括号来实现,就像这样:

val a = 2                                       //> a  : Int = 2
val b = 3                                       //> b  : Int = 3
val squareSum = { val sum = a + b; sum * sum }  //> squareSum  : Int = 25

在这里,分号和单词“in”之间没有重大区别(或者您可以将表达式移至下一行,并假装“in”是隐含的,如果这使它更像OCaml:D)。

val squareSum = {
  val sum = a + b // in
    sum * sum
}
另外,更深入技术的看法是:Scala中类似Clojure的'let'。我认为生成的结构与多语句形式相比相当晦涩。

这是我目前的做法,显然是100%正确的。我只是想知道是否有一种只使用表达式的方法来完成它(我真的很喜欢OCaml中let表达式的可读性)。 - GJK
2
其实我只是好奇是否可以仅使用表达式(因此没有返回Unit的val或语句)编写Scala代码。我并不打算以这种方式编程,我只是有点好奇。(好吧,你抓住我了。我对Lisp很着迷。) - GJK
我明白你的观点。我的看法是这是一个关于函数纯净性的问题,而不是可读性,因为很难争论“in”形式实际上更可读或更清晰(或不是;它只是不同)。但这并不否定它的存在价值。我认为你无法在没有实际语言支持(新的关键字)的情况下完成它。我不认为你能编写一个像这样工作的in后缀运算符。 - Rob Napier
话虽如此,如果我要进一步探索这个问题,我可能会研究宏、宏注解和准引用。在Scala中有很多有趣的调整方式(特别是在2.11版本中)。我没有完整的答案,但这是我开始研究如何创建一个let...in结构的地方。 - Rob Napier
你可能还想看一下 scalaz(typelevel.org)。它为 Scala 添加了更多的函数式组件。 - Rob Napier
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接