1

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

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
4

2 回答 2

3

To add to Jeffrey's answer, it looks like you meant to add items to listdoor in three steps. The confusion is about the meaning of ; and :: in ocaml. And you and I are both in the habit of programming by doing sequences of steps, as we did in other languages.

Everything to the right of = is one big expression that evaluates to the function's return value. That's how values are returned from functions in ocaml.

When the expression has ;'s in it, the ; is a delimiter between sub-expressions. Each sub-expression gets evaluated, and all the return values except for that of the last sub-expression get discarded (those sub-expressions aren't useless though - the reason for using ; is to accumulate side-effects).

But the :: doesn't act by side effect - cons is just a function with a return value.

So your lines countZero(doorlist,count) :: listdoor and countOne(doorlist,count) :: listdoor each produced a new list, but each of those lists was discarded.

If you want to keep the meaning the same, and build up a list in sequence, you could do it by storing the steps of the accumulation using let and 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
;;

If keeping all those intermediate names around seems less efficient than the series of concatenations you had in mind in your posting, it's because this kind of thing is more terse if you express the function in a way that resembles the verbal description you gave, instead of the sequential way that you were encouraged to come up with by other languages. If you want to collect the result of three functions into a list, you can simply do this:

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

Do you see how the return value (everything to the right of =) matches up with the description you gave for your function: "which is supposed to be a list containing the output of the functions"? (NB: semicolons within the square brackets delimit elements in a list - different meaning from the ;'s earlier!)

Two other minor points:

If the function you are defining doesn't call itself, there is no need to declare it 'rec'. But maybe Jeffrey's hunch is right and in fact you meant to have some recursive calls here somewhere.

There's no need to make a name for your return value (listdoor in your case). If the function's definition is very short like this one, let the definition itself be your 'label' for the return value. In the last code block, the function doesn't give a name to the list it returns.

于 2012-09-29T09:59:38.160 回答
2

我想说我看到的最大问题是,let x = value它只在顶层才有意义。在其他构造中,唯一可用的形式是let x = value in y. 所以,你错过了这个in部分。

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

于 2012-09-27T18:00:33.710 回答