for-loop - 为什么闭包中允许使用 'for .. in'?

标签 for-loop foreach f# closures immutability

闭包中不允许使用可变值,但 for .. in 表达式可以。在 C# 中,for 循环更新迭代器,但在 F# 中却不像看起来那样。如何以及为何?

最佳答案

F# 的 for .. in 相当于 C# 的 foreach 循环,而不是 C# 的 for 循环。从 C# 5 开始,foreach 循环不会更新迭代器;相反,它会为循环中的每次迭代创建一个新变量(这对闭包有重要影响;有关详细信息,请参阅 Foreach now captures variables! (Access to modified closure)。这也是 F# 所做的:如果您编写

for txt in ["abc"; "def"; "ghi"] do
    printfn "%s" txt

那么当您运行该循环时,您实际上创建了三个个新字符串变量,而不仅仅是一个。

为了向自己证明 F# 每次都会创建一个新变量,请尝试以下功能不太强大的代码:

let actions = new System.Collections.Generic.List<System.Action<unit>>()
for txt in ["abc"; "def"; "ghi"] do
    actions.Add(fun () -> printf "%s " txt)
for action in actions do
    action.Invoke()

如果 txt 每次通过 for .. in 循环都是相同的变量,这将打印 ghi ghi ghi,就像 C# 一样4 及更早版本会有 -- 因为匿名函数关闭了变量,并且在循环之后变量包含 ghi。但如果您运行上面的代码,您会看到它打印 abc def ghi,就像 C# 5 及更高版本所做的那样。

所以你的问题的答案是 F# 允许在闭包中使用 for .. in 因为它实际上并没有改变任何东西

关于for-loop - 为什么闭包中允许使用 'for .. in'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38499991/

相关文章:

如果属性有多个值,同时复制其他值,则 Powershell 拆分 PSCustomObject

f# - 使用 F# 的 `ref` 与 `mutable` 赋值运算符

f# - F# 中通用约束函数的内存

javascript - 使用 JavaScript 进行 SQLite SELECT

python - 如何简化 Python 和 Matlab 中的 for 循环

javascript - 如何循环数组显示表格所有行的所有数据?

php - mysqli_fetch_assoc 返回为 foreach() 提供的参数无效

collections - list.map 和 list.collect 的区别

javascript - 使用 jQuery 在 for 循环中正确 append 元素

java - ArrayList、for 循环和 if 语句的问题 - 打印列表中每个项目的行