2012-02-03 80 views
2

我是OCaml的一名完全新手,並試圖創建一個簡單的控制檯程序。爲什麼此代碼在交互中工作,但編譯時失敗?

(*let k = read_int() 
let l = read_int() 
let m = read_int() 
let n = read_int() 
let d = read_int()*) 

let k = 5 
let l = 2 
let m = 3 
let n = 4 
let d = 42 

let rec total: int -> int -> int = fun i acc -> 
    if i > d then 
    acc 
    else 
    if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then 
     total (i + 1) (acc + 1) 
    else 
     total (i + 1) acc; 

print_int (total 1 0) 

但是,如果我嘗試編譯它,它失敗:

PS C:\Users\user> ocamlc -g .\a148.ml 
File ".\a148.ml", line 14, characters 2-180: 
Warning S: this expression should have type unit. 
File ".\a148.ml", line 22, characters 0-21: 
Error: This expression has type unit but is here used with type int 

所以,看起來像if表達不能在這裏返回值(爲什麼?)。我已經添加了let結合

let k = 5 
let l = 2 
let m = 3 
let n = 4 
let d = 42 

let rec total: int -> int -> int = fun i acc -> 
    let x' = if i > d then 
     acc 
    else 
     if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then 
    total (i + 1) (acc + 1) 
     else 
    total (i + 1) acc; 
    x' 
print_int (total 1 0) 

和它的作品,但引發了另一個錯誤:

File ".\a148.ml", line 23, characters 0-0: 
Error: Syntax error 

第23行是旁邊print_int聲明和空的,所以它看起來像編譯器我想別的東西,但我不知道是什麼。

UPD:確定,所述工作碼:

let k = 5 in 
let l = 2 in 
let m = 3 in 
let n = 4 in 
let d = 42 in 
let rec total i acc = 
    if i > d then 
    acc 
    else 
    if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then 
     total (i + 1) (acc + 1) 
    else 
     total (i + 1) acc 
in let x = total 1 0 in 
print_int x; 

回答

2

問題是分號(;)的誤用。

分號有意成爲兩個表達式的序列組合。 S1 ; S2表示編譯器預計S1類型爲unit類型,按該順序計算S1S2並返回S2的結果。

在這裏你錯誤地使用;,所以OCaml期望第二個if...then...else返回unit並希望你提供一個表達式。卸下;並添加必要的in(S)應該做的函數編譯:

let k = 5 in 
let l = 2 in 
let m = 3 in 
let n = 4 in 
let d = 42 in 

let rec total: int -> int -> int = fun i acc -> 
    if i > d then 
    acc 
    else 
    if (i mod k) == 0 || (i mod l) == 0 || (i mod m) == 0 || (i mod n) == 0 then 
     total (i + 1) (acc + 1) 
    else 
     total (i + 1) acc 

關於你的第二個功能,你應該in取代;,表明x'用來計算返回值。

順便說一下,你的total函數看起來很奇怪,因爲你在函數體中使用lambda表達式。顯式聲明的可讀性:

let rec total i acc = 
    if i > d then 
     acc 
    else if i mod k = 0 || i mod l = 0 || i mod m = 0 || i mod n = 0 then 
     total (i + 1) (acc + 1) 
    else 
     total (i + 1) acc 

我也改變了參考平等(==)結構性平等(=)雖然沒有在整數它們之間沒有什麼區別。

+0

它不取決於是否呈現分號,我嘗試了不同的變化。如果我在第一種情況下刪除分號,則會引發錯誤「File」。\ a148.ml「,第20行,字符6-11: 錯誤:此函數應用於太多參數, 可能您忘記了'; ' – 2012-02-03 11:49:08

+0

謝謝,我添加了lambda只是爲了註釋函數類型並檢查錯誤。我應該閱讀更多關於範圍的內容,當我出於某種原因在'in'裏面加入整個東西的時候,它是有效的。 – 2012-02-03 12:03:36

+0

這很明顯,因爲你在'total'中使用'k','l','m','n'和'd'。如果它們是恆定的,我更願意將它們放在「總體」中。否則,他們應該成爲參數。 – pad 2012-02-03 12:12:29

相關問題