这个语法在 OCaml 中来自哪里?

Where does this syntax come from in OCaml?

this video 中介绍了使用 oUnit 进行的单元测试。测试是由这样的代码片段定义的:

let test_fixture = "SimpleMath" >:::
[
    "add" >:: (fun () -> 
      assert_equal 4 (SimpleMath.add 2 2);
      assert_equal 0 (SimpleMath.add 0 0)
      );

    "subtract" >:: (fun () -> 
      assert_equal 4 (SimpleMath.subtract 9 3);
      assert_equal 3 (SimpleMath.subtract 5 2)
      )
 ]

let _ = run_test_tt test_fixture

为什么要使用单分号?我在 类 中学到,您总是使用双分号来表示指令。为什么我们要将 return 值分配给模式? run_test_ttrun_test_tt_main有区别吗?我在文档中找不到它。

来自另一个例子

let test1 test_ctxt = assert_equal "x" (Foo.unity "x");;

为什么我们要将类型 (!) 设置为函数参数?

单个分号(本质上)是一个运算符,它通过忽略第一个表达式的值并返回第二个表达式的值来组合两个表达式。

换句话说,对于命令式代码,它在许多其他语言中的作用类似于分号。

双分号是一种特殊符号,它告诉顶层您希望它评估您目前输入的内容。以我(拙见)的观点,你应该只在顶层输入代码时使用它。它与 ; 运算符没有实际关系。

似乎有一个相当普遍的误解,认为 ;; 是 OCaml 语法的某种重要部分。我不这么认为;它只是与顶层通信的一种方式(类似于 #use#show_module)。

更新

你问能不能这样写:

let x = 4; print_int x

答案是否定的,你不能这样写。但这是因为 x 没有以前的值。这段代码解析如下:

let x = (4; print_int x)

如您所见,这会尝试打印 x 的先前值。评估 print_int 时,新的 x 尚未绑定。

OCaml中定义局部变量的方式是let var = expr1 in expr2。所以你可以只输入 let x = 4 in print_int x。 (我个人不明白为什么分号会更好。)

你说如果删除 ;;,你的代码将无法解析。如果您在模块的顶层混入命令式代码,就会发生这种情况。我的解决方案就是不这样做。所以不要在模块中写这样的东西:

Print.printf "Welcome to module\n"

我这样写:

let () = Printf.printf "Welcome to module\n"

如果您的示例出现在模块的顶层,我会这样写:

let x = 4
let () = print_int x

(注意,根本没有分号!)

另请注意,您原始帖子中的代码遵循此约定,除了他们写 let _ = ... 而不是 let () = ...