我的教授今天向我们展示了这段代码,但我似乎无法理解它的结果:
# let a = 2;;
val a : int = 2
# let f = fun x -> fun y -> if x = y then a + 2 else a - 10;;
val : f 'a -> 'a -> int = <fun>
# f 1 (2 - 1);;
- : int = 4
# let a = 18;;
val a : int = 18
# f 1 (2 - 1);;
- : int = 4
???所以基本上,我希望看到这个结果:
- : int = 20
为什么这不是输出?
答案 0 :(得分:7)
这是因为let a
确实引入了具有相同名称的 new 变量,但该函数仍然引用其范围内的变量 - 它是closure,并且它关闭的变量是一个常数。它不会在调用它的范围内动态查找变量名。
您可以通过在可以分配给的变量中存储mutable reference来实现预期的行为:
# let a = ref 2;;
let f = fun x -> fun y -> if x = y then !a + 2 else !a - 10;;
f 1 (2 - 1);;
- : int = 4
# a := 18;;
f 1 (2 - 1);;
- : int = 20
然而,请注意,这通常是不希望的。变量应该是常量,这样我们可以争论函数f
在调用它时总是返回4
或8
,而不是让结果取决于哪个值和何时值是分配给参考单元格。尽可能避免使用它们。在这个特定的例子中,人们可以这样做:
let f a x y = 2 + if x = y then 2 else -10 in
let g = f 2 in
print_int (g 1 (2-1));
let h = f 18 in
print_int (h 1 (2-1));;