在OCaml中使用匹配语句控制流:意外的早期返回

时间:2017-11-06 02:14:55

标签: ocaml

我认为我可能对如何将表达式定义为OCaml match语句中的模式的有效目标存在根本的误解。在这个简单的例子中,我无法理解程序的控制流行为。

open Printf

let () =
  let a = None in
  match a with
  | Some s -> printf "%s\n" s
  | None -> printf "None.\n";
  printf "Here.\n";
  let b = Some "string" in
  match b with
  | Some s -> printf "%s.\n" s
  | None -> printf "None.\n";
  printf "There.\n"

根据我目前对控制流的理解,我希望输出为:

None.
Here.
string.
There.

但是入口点函数在到达printf "There.\n"之前就返回了。我注意到这只发生在最后一个模式以外的模式匹配时。到目前为止,我已经尝试过我在其他地方看到的用于在此上下文中对多个表达式进行分组的方法,如beginend,但无济于事。有没有更好的方法在match表达式中对序列语句进行分组,或者我只是滥用构造?

1 个答案:

答案 0 :(得分:2)

match之后->语句的部分可以包含任意数量的以分号分隔的语句。所以你的代码应该像这样缩进:

let () =
  let a = None in
  match a with
  | Some s -> printf "%s\n" s
  | None -> printf "None.\n";
            printf "Here.\n";
            let b = Some "string" in
            match b with
            | Some s -> printf "%s.\n" s
            | None -> printf "None.\n";
                      printf "There.\n"

预期输出为:

None.
Here.
string.

<强>更新

您可以使用括号(或使用在OCaml中完全等效的begin/end)来获得与缩进相对应的排序:

let () =
  let a = None in
  (match a with
  | Some s -> printf "%s\n" s
  | None -> printf "None.\n"
  );
  printf "Here.\n";
  let b = Some "string" in   
  (match b with
  | Some s -> printf "%s.\n" s
  | None -> printf "None.\n"
  );
  printf "There.\n"

旁注:这是begin/end的一个例子:

# begin 3 + 5 end * 7;;
- : int = 56

确实如此,圆括号和begin/end在OCaml中是等效的。