2017-09-04 68 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是一個不純粹的傻瓜在這種情況下比純粹的傻瓜更糟? –

相關問題