提问人:user1443098 提问时间:5/6/2017 更新时间:5/6/2017 访问量:327
F# 理解循环 vars 可变?
F# comprehension loop vars mutable?
答:
7赞
TheInnerLight
5/6/2017
#1
不,它不是一个可变变量。我们可以通过创建函数来看到这一点,我们稍后会调用这些函数来打印它。
观察:
let printIs = [for i in 1..10 do yield fun () -> printf "%i " i]
printIs |> List.iter (fun f -> f())
这将返回:
1 2 3 4 5 6 7 8 9 10
请注意,每个 1..10 值都是打印的,因此不能是可变变量,因为如果是,则在循环完成后将始终具有该值。实际上,该符号在列表推导的每一步中都引用了不同的不可变值。i
i
10
i
如果我尝试使用实际的可变变量来执行此操作,我会得到不同的行为:x
let mutable x = 1
let printIs2 =
[for i in 1..10 do
x <- i
yield fun () -> printf "%i " x]
printIs2 |> List.iter (fun f -> f())
这将返回:
10 10 10 10 10 10 10 10 10 10
评论
0赞
user1443098
5/6/2017
但是你循环中的“i”会变异,不是吗?它依次采用值 1 到 10。
0赞
TheInnerLight
5/6/2017
@user1443098 不,它不会变异。如果它确实发生了变异,它的行为将类似于第二个示例,并且每次都打印,因为我们在循环完成后打印值。相反,这告诉你,在列表推导的每一步中都引用了不同的不可变值。10
i
0赞
user1443098
5/6/2017
啊!这就是我所缺少的一点!所以,“我指的是一个不同的不可变值”非常感谢!
0赞
user1443098
5/7/2017
我发现有趣的是,Python 中的等效代码会产生不同的结果:确实打印了 10 个 10。但那是因为 Python 的后期绑定行为,IIUC,当调用 lambda 时,i 的值为 10。printIs = [lambda : print (i) for i in range(1,11)] ;for f in printIs: f()
1赞
Tomasz Maczyński
5/7/2017
不错的答案。顺便说一句:在 C# 中,绑定在 foreach 循环中的变量存在很多混淆,这导致了 C# 版本 5 的重大更改。问题并不相同,但性质非常相似。
下一个:F# 从可变更改为 ref
评论