2012-02-03 52 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

相关问题