我在文件mod.ml
中定义了一个模块,如下所示:
module Area = struct
...
let test : unit =
Print.printf "haha"
...
end;;
Print.printf "hehe";;
Area.test
似乎在;;
之后没有end
,我无法按ocamlc
编译代码。但是我在Ocaml文件中使用;;
看起来很奇怪,我是否必须保留它们?
按mod
生成ocamlc
后,我启动mod
,打印hahahehe
。似乎haha
按let test : unit ...
的定义打印,而不是其Area.test
。我的结果是hehehaha
或hahahehehaha
。谁能解释为什么它不是我的预期呢?
答案 0 :(得分:4)
我从未在源文件中使用;;
,我认为它是顶级界面的一部分。对于你的代码,我可能会写:
module Area = struct
let test : unit -> unit =
fun () -> Printf.printf "haha"
end
let () =
Printf.printf "hehe";
Area.test ()
对于它的价值,Area.test
如你所定义的那样它不是一个函数,它只是一个在计算过程中带有副作用的单位值。在我的代码中,我已将其更改为unit -> unit
类型的函数。
答案 1 :(得分:4)
当ocamlc
加载模块时,它会按照定义的顺序评估所有“顶层”定义。在您的情况下,您有三个“顶级”定义。
第一个是值unit
(类型unit
的唯一值),它绑定到名称“test”。副作用后生成此值:显示“haha”(此处模块Area
用作命名空间,不会延迟计算);
seconde one也是值unit
,但没有名字绑定;此值也会产生副作用:显示“hehe”;
最后一个只是与名称“test”相关联的值,即。 unit
。但是,这次没有副作用,因为已经生成了与名称“test”相关联的值unit
。
如果您希望每次调用test时都有副作用,则需要使用函数:
let test () = Print.printf "haha"
对于问题的;;
部分。解析器需要这些来知道表达式何时结束。还有其他方法可以帮助解析器,例如:
let () = Print.printf "hehe"
或者简单地说:
let _ = Area.test
最新版本更短,因为您不必指出类型信息,但更容易出错,因为编译器在部分应用时不会让您感到温暖。