2017-09-04 71 views
0

我的教授今天向我们展示了这个代码,但我似乎无法理解它的结果:OCaml - 为什么函数没有改变它的输出?

# 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 

为什么不是这个输出?

回答

7

这是因为let a确实把具有相同名称的变量,但功能还是指一个在其范围内 - 这是一个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在被调用时总是返回48,而不是取决于哪个值被分配给参考单元的地点和时间。避免他们在可能的地方。在这个特定的例子中,可以这样做:

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));; 
+1

不要显示对学生的引用,你这个傻瓜! :-p – PatJ

+1

@PatJ正是我的想法:-)我会编辑一个适当的警告 – Bergi

+0

@PatJ是一个不纯粹的傻瓜在这种情况下比纯粹的傻瓜更糟? –

相关问题