我试图从这里理解OCAML并运行遵循代码:
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*)
任何解释都将不胜感激。
ocaml是一种基于表达的语言。它没有语句,因此;
不是语句终结者,而是序列运算符(类似于C的逗号运算符(。<expr1>; <expr2>
大约只是let () = <expr1> in <expr2>
的短手。它评估expr1
,丢弃其值,然后评估expr2
并返回该值。
let <pattern> = <expr1> in <expr2>
是一种表达式,根据<pattern>
绑定expr1
的结果,在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;;
to
let () = ...;;
除非您要多次使用命名功能。