scala 闭包问题

发布于 2022-09-06 11:57:34 字数 524 浏览 18 评论 0

scala 的三个函数如下所示,正确调用三个函数返回的函数签名是一样的,但是不明白三个函数不同之处到底代表什么?

直观上看 f1 和 f3 都是不接受任何参数,但是使用上 f1 可以使用省略括号和使用空括号两种方式,f3 则不能使用空括号。f1 和 f3 两个函数有什么区别呢?这种区别是 scala 的特性呢还是bug呢?

f1 和 f2 函数体内返回 pp 函数的时候使用不使用 “_“ 都是返回了函数。不使用 "_" 也并没有当成函数调用去编译然后报错。请问这个该怎么理解呢?

def f1(): String => Unit = {
  def pp(s: String): Unit = println(s)
  pp
}

def f2(): String => Unit = {
  def pp(s: String): Unit = println(s)
  pp _
}

def f3: String => Unit = {
  def pp(s: String): Unit = println(s)
  pp
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独岁月 2022-09-13 11:57:34

首先,要明确在 Scala 中如果一个方法不接受参数,那么可以不使用 () 调用它:

scala> 2.toString()
res1: String = 2

等价于:

scala> 2.toString

但是在定义函数时,方法是否有括号则很重要。对于楼主的函数:

def f1(): String => Unit = {
  def pp(s: String): Unit = println(s)
  pp
}

def f3: String => Unit = {
  def pp(s: String): Unit = println(s)
  pp
}

编译器认为 f1f3 不等价。对于 f1 我们可以不加括号调用它,也可以加上括号;但是 f3 就一定不能加上括号。这是一个 feature 而不是 bug可以参考我的这篇文章:有括号方法和无括号方法区别。在结构类型(Structural Type)中,这两者定义是有区别的。

再谈谈 f1f2 的区别。实际上 f1 返回的函数是 ppf2 返回的是一个匿名函数,这样匿名函数其实是:

s => pp(s)

这就是 _ 的作用。它实际上是一个占位符,表示接受一个参数。楼主也可以写成:

def f2(): String => Unit = {
  def pp(s: String): Unit = println(s)
  pp(_)  // 返回一个匿名函数,而不是 pp 了
}

回到楼主的例子中:

val c = b _

就等价于:

val c = () => b

另外,这三个函数在我理解看来不是闭包哦。闭包可以理解为在函数中引用了函数外部的变量,

无声无音无过去 2022-09-13 11:57:34

没人回答就自问自答吧。
_ 我感觉就是个包装器,类似于

def f(s:String)(r:String) = println(s"$s passed, and then $r passed")

val a = f("hello") _

就相当于

val a = (r:String) => f("hello")(r)

对于 val b = 4 使用 val c = b _ 也会使得c成为一个匿名函数,函数签名为 ()=>Int
但是具体的机制怎么样还没弄明白。。。
对于函数 f3,是关于 pp 的使用,pp 编译器怎么编译 pp 取决于 pp 出现的位置。pp 首先是一个对象,function1 之类的对象。有些地方会把 pp 当作函数调用,有些地方会把 pp 当作 函数对象。

这两天写代码的一些感想,不严格。。。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文