为什么这段代码在交互式中工作但在编译时失败?

时间:2012-02-03 11:36:58

标签: ocaml

我在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;

1 个答案:

答案 0 :(得分:2)

问题是滥用分号(;)。

分号打算成为两个表达式的序列组合。 S1 ; S2表示编译器希望S1unit类型,按该顺序计算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'用于计算返回值。

BTW,你的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

我还将引用相等(==)更改为结构相等(=),尽管它们之间在整数方面没有区别。