ocaml代码中的()和`in`的需求和目的

时间:2019-05-02 05:46:12

标签: ocaml

我试图了解Ocaml,并从here运行以下代码:

let rec fib n =  
  if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main () =
  let arg = int_of_string Sys.argv.(1) in
  print_int (fib arg);
  print_newline ();
  exit 0;;
main ();;

但是,我不明白为什么需要()in以及为什么以下代码(更简洁的代码)不起作用:

let rec fib n =
  if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main =
  let arg = int_of_string Sys.argv.(1);
  print_int (fib arg);
  print_newline;
  exit 0;;  (* Line 7. Error is coming from here.*)
main;;

以上代码给出以下错误:

File "fib_simpler.ml", line 7, characters 8-10:
Error: Syntax error

我注意到删除()仅给出警告,而删除in则给出错误,程序停止执行。

在print_newline之后保留in()会删除所有警告和错误。因此,()关键字实际上并不需要main

以上显示在下面的注释中:

let rec fib n =  (*(n) also works here*)
  if n < 2 then 1 else fib (n-1) + fib (n-2);;
let main () =  (*removing () here does not matter*)
  let arg = int_of_string Sys.argv.(1) in (* in keyword is essential here*)
  print_int (fib arg);
  print_newline ();  (*removing () causes warning *)
  exit 0;;
main ();;      (*removing () here does not matter*)

任何解释将不胜感激。

1 个答案:

答案 0 :(得分:1)

OCaml是一种基于表达式的语言。它没有语句,因此;不是语句终止符,而是序列运算符(类似于C的comma operator)。 <expr1>; <expr2>大约只是let () = <expr1> in <expr2>的简写。它将评估expr1,丢弃其值,然后评估expr2并返回该值。

let <pattern> = <expr1> in <expr2>是根据expr1绑定<pattern>结果的表达式,例如在{的上下文中,它可能只是一个简单的标识符或一个更复杂的记录模式{1}}。由expr2创建的绑定将不在<pattern>之外。

在绑定中使用expr2(称为“单元”)定义一个函数。如果省略该参数,则不是在定义函数,而只是定义一个值。区别在于,值会立即(仅一次)求值,而函数在通过调用参数来“调用”时将求值。必须将期望()作为参数的函数赋予()作为执行它的参数,否则,您只是在传递函数本身。而且,如果像上面那样丢弃它,几乎总是一个错误。因此,警告。

简而言之:

  • ()而不用let arg = int_of_string Sys.argv.(1); ...分隔两个表达式是语法错误。直到到达当前表达式的结尾并发现那里没有in时,编译器才意识到这一点。

  • in ...定义一个函数

  • let main () =定义一个值

  • let main = ...将参数print_newline (); ...应用于(),从而执行它,然后丢弃返回值

  • print_newline并没有做任何事情

最后,如果您只执行一次print_newline; ...,则可以减少

main

let main () = ...;;
main;;

除非您要多次使用它,否则不需要命名函数。