首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >scala闭包-强制绑定到值而不是引用

scala闭包-强制绑定到值而不是引用
EN

Stack Overflow用户
提问于 2016-04-30 21:47:20
回答 1查看 101关注 0票数 2

我有一个返回一个简单函数数组的方法,该数组只打印它们的订单号:

代码语言:javascript
复制
def buggyClosureFunction(amount: Int) = {
  val functions = new Array[() => Unit](amount);
  var i = 0;
  while (i < amount) {
    functions(i) = {()=>print(i + " ")}
    i += 1;
  }
  functions
}

 val wow = buggyClosureFunction(4);
 wow.foreach(_());

这将打印4 4 4。(所有函数都打印它们引用的i值。我似乎不能改变我的方法,这样返回的函数就会打印出12,2,3,4。

我的一次尝试是:

代码语言:javascript
复制
def goodClosureFunction(amount: Int) = {
  val functions: = new Array[() => Unit](amount);
  var i = 0;
  val helper = (num: Int) => {
    print(num);
  }

  while (i < amount) {
    functions(i) = {()=>helper(i)()}
    i += 1;
  }
  functions
}

但这个仍然印着44-4。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-30 21:57:08

当您关闭var i = 0时,Scala编译器将将iscala.Int转换为scala.runtime.IntRef,并将其提升到编译器生成的类中。这意味着生成的类保存对上述类型的引用。当函数被执行时,该值实际上指向最后一个值,而不是保存每个迭代的值。

为了避免这种情况,在闭包中创建i的本地副本:

代码语言:javascript
复制
while (i < amount) {
  functions(i) = {
    val j = i
    () => print(j + " ")
  }
  i += 1;
}

正如@Łukasz所指出的,如果您想使用函数式方法并避免闭包麻烦和可变状态:

代码语言:javascript
复制
def nonBuggyNoClosure(n: Int) = (0 until n) map (i => () => print(i + " "))

更详细地介绍How are closures implemented in scala?中Scala闭包的实现细节

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36960616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档