Ocaml 为什么在顶级之外的一些语句中需要双分号

Ocaml 为什么在顶级之外的一些语句中需要双分号,ocaml,Ocaml,我有以下两行代码: let a = [1;2;3;4;5;6;7;8;9;0] print_string (String.concat " " (List.map string_of_int a)) 它给了我这个错误: 文件“test.ml”,第65行,字符0-0: 错误:语法错误 但是,如果我以双分号结束该行: let a = [1;2;3;4;5;6;7;8;9;0];; print_string (String.concat " " (List.m

我有以下两行代码:

let a = [1;2;3;4;5;6;7;8;9;0]
print_string (String.concat " " (List.map string_of_int a))
它给了我这个错误:

文件“test.ml”,第65行,字符0-0: 错误:语法错误

但是,如果我以双分号结束该行:

let a = [1;2;3;4;5;6;7;8;9;0];;
print_string (String.concat " " (List.map string_of_int a))
它很好用


我已经读过了,双分号应该只在顶层使用,为什么我需要它呢。如果我没有,我应该写什么呢?

可以使用双分号来引入顶级表达式:

let x = 0
let do_something () = Printf.printf "x=%d" x
;; do_something ()
;; do_something ()
这里没有分隔的
第一个
do\u something()
仍然是函数“do\u something”定义的一部分

通常认为使用单元顶级绑定更为惯用:

let x = 0
let do_something () = Printf.printf "x=%d" x
let () =
  do_something (); do_something ()

双分号可用于引入顶级表达式:

let x = 0
let do_something () = Printf.printf "x=%d" x
;; do_something ()
;; do_something ()
这里没有分隔的
第一个
do\u something()
仍然是函数“do\u something”定义的一部分

通常认为使用单元顶级绑定更为惯用:

let x = 0
let do_something () = Printf.printf "x=%d" x
let () =
  do_something (); do_something ()

所以我应该写
let a=[1;2;3;4;5;6;7;8;9;0]let()=print_string(string.concat”“(List.map string_of_int a))
来代替吗?是的。它通常只需要在程序中的一个地方,对于入口点:
let main()=(*做所有事情*)。。。让()=main()
需要理解的两件事是:
分离顶级短语,并且您永远不需要它,除非在玩交互式顶级循环时。短语可以是:(1)任意长的全局let定义序列、类型定义、模块定义等;(2)单个表达式,或(3)特殊指令(如
#require“somepackage”
)。在典型的编译源代码中,您从不使用
正如您通常编写一个类似(1)的短语一样,可能使用
let()=…
习惯用法来执行操作。种类(2)和(3)用于交互顶层。所以我应该写
让a=[1;2;3;4;5;6;7;8;9;0]let()=打印字符串(string.concat”“(List.map string\u of_int a))
,而不是吗?是的。它通常只需要在程序中的一个地方,对于入口点:
let main()=(*做所有事情*)。。。让()=main()
需要理解的两件事是:
分离顶级短语,并且您永远不需要它,除非在玩交互式顶级循环时。短语可以是:(1)任意长的全局let定义序列、类型定义、模块定义等;(2)单个表达式,或(3)特殊指令(如
#require“somepackage”
)。在典型的编译源代码中,您从不使用
正如您通常编写一个类似(1)的短语一样,可能使用
let()=…
习惯用法来执行操作。类型(2)和(3)用于交互顶层。您只需要在REPL中使用它们,而不需要在文件中使用它们…您只需要在REPL中使用它们,而不需要在文件中使用它们。。。