gpt4 book ai didi

scala - 关闭 Scala 中的循环变量

转载 作者:行者123 更新时间:2023-12-03 14:35:11 26 4
gpt4 key购买 nike

正如埃里克·利珀特 (Eric Lippert) 的博客文章 Closing over the loop variable considered harmful 中所讨论的那样,在 C# 中关闭循环变量可能会产生意想不到的后果。我试图了解是否同样的“陷阱”适用于 Scala .

首先,由于这是一个 Scala 问题,我将尝试解释 Eric Lippert 的 C# 示例,并在他的代码中添加一些注释

// Create a list of integers
var values = new List<int>() { 100, 110, 120 };

// Create a mutable, empty list of functions that take no input and return an int
var funcs = new List<Func<int>>();

// For each integer in the list of integers we're trying
// to add a function to the list of functions
// that takes no input and returns that integer
// (actually that's not what we're doing and there's the gotcha).
foreach(var v in values)
funcs.Add( ()=>v );

// Apply the functions in the list and print the returned integers.
foreach(var f in funcs)
Console.WriteLine(f());

大多数人期望这个程序打印 100、110、120。它实际上打印了 120、120、120。
问题在于 () => v我们添加到 funcs 的函数list 关闭 v 变量,而不是 v 的值。当 v 改变值时,在第一个循环中,我们添加到 funcs 的所有三个闭包列出“看到”相同的变量 v,它(当我们在第二个循环中应用它们时)对所有变量都具有 120 值。

我试图将示例代码翻译成 Scala:
import collection.mutable.Buffer
val values = List(100, 110, 120)
val funcs = Buffer[() => Int]()

for(v <- values) funcs += (() => v)
funcs foreach ( f => println(f()) )
// prints 100 110 120
// so Scala can close on the loop variable with no issue, or can it?

Scala 确实没有遇到同样的问题,还是我刚刚翻译了 Eric Lippert 的代码并且未能重现它?

这种行为已经让许多勇敢的 C# 开发人员绊倒了,所以我想确保 Scala 没有奇怪的类似问题。而且,一旦你理解了为什么 C# 的行为方式如此,Eric Lippert 的示例代码的输出就有点意思(基本上就是闭包的工作方式):那么 Scala 有什么不同呢?

最佳答案

Scala 没有同样的问题,因为 v不是一个var,它是一个val。因此,当你写

() => v

编译器知道它应该生成一个返回该静态值的函数。

如果您使用 var ,你可能会遇到同样的问题。但更清楚的是,这是请求的行为,因为您显式创建了一个 var,然后让函数返回它:
val values = Array(100, 110, 120)
val funcs = collection.mutable.Buffer[() => Int]()
var value = 0
var i = 0
while (i < values.length) {
value = values(i)
funcs += (() => value)
i += 1
}
funcs foreach (f => println(f()))

(注意,如果你尝试 funcs += (() => values(i)) 你会得到一个越界异常,因为你已经关闭了变量 i,当你调用它时,现在是 3 !)

关于scala - 关闭 Scala 中的循环变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9842476/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com