Ocaml函数中的语法错误

时间:2012-09-27 17:53:03

标签: function ocaml

我在这个函数的最后一行收到语法错误:

let rec countAll(doorlist, count) =
    let listdoor = [];
    countZero(doorlist, count) :: listdoor;
    countOne(doorlist, count) :: listdoor;
    countTwo(doorlist, count) :: listdoor;;

我可能会对如何从Ocaml函数返回内容感到困惑。我想返回“listdoor”,它应该是一个包含函数countZero,countZero和countTwo输出的列表。

我在最后一个lint上遇到语法错误,这段代码的最后几个字符:

File "MonteeHall.caml", line 30, characters 38-40:
Error: Syntax error

2 个答案:

答案 0 :(得分:3)

要添加到Jeffrey的答案,看起来您打算通过三个步骤将项目添加到listdoor。混淆是关于ocaml中;::的含义。你和我都习惯于按照一系列步骤进行编程,就像我们在其他语言中所做的那样。

=右边的所有内容都是一个大的表达式,用于计算函数的返回值。这就是从ocaml中的函数返回值的方式。

当表达式中包含;时,;是子表达式之间的分隔符。每个子表达式都会被计算,除了最后一个子表达式之外的所有返回值都被丢弃(这些子表达式虽然没用,但使用;的原因是累积副作用) 。

但是::没有副作用 - 缺点只是一个带有返回值的函数。

因此,您的行countZero(doorlist,count) :: listdoorcountOne(doorlist,count) :: listdoor 各自生成了一个新列表,但每个列表都被丢弃了。

如果你想保持意义相同,并按顺序建立一个列表,你可以通过使用let和in存储累积的步骤来实现:

let countAll(doorlist,count) =
    let step1 = [] :: countZero(doorlist,count) in
    let step2 = step1 :: countOne(doorlist,count) in
    let step3 = step2 :: countTwo(doorlist,count) in
    step3
;;

如果保留所有这些中间名称似乎比你在帖子中记住的一系列连接效率低,那是因为如果你以类似你给出的口头描述的方式表达这种功能,这种事情会更简洁而不是你鼓励用其他语言提出的顺序方式。如果要将三个函数的结果收集到列表中,可以这样做:

let collectResults (a,b) = 
    [ fun1 (a,b) ;  fun2 (a,b) ; fun3 (a,b) ]
;;

您是否看到返回值(=右侧的所有内容)与您为函数提供的描述相匹配:“哪个应该是包含函数输出的列表”? (注意:方括号内的分号分隔列表中的元素 - 与;之前的含义不同!)

另外两个小问题:

如果您定义的函数没有调用自身,则无需声明它'rec'。但也许Jeffrey的预感是正确的,事实上你的意思是在某处有一些递归调用。

您无需为返回值命名(在您的情况下为listdoor)。如果函数的定义非常短,请将定义本身作为返回值的“标签”。在最后一个代码块中,该函数没有为它返回的列表命名。

答案 1 :(得分:2)

我认为我看到的最大问题是let x = value仅在顶级有意义。在其他构造中,唯一可用的形式是let x = value in y。所以,你错过了in部分。

一般来说,我建议首先谨慎使用;。您必须将OCaml函数视为一个大表达式(带有值)。它不像程序语言那样有一系列动作(要做的事情)。