我试图了解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*)
任何解释将不胜感激。
答案 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;;
除非您要多次使用它,否则不需要命名函数。