我是Ocaml的新手,并试图编写一些小的示例应用程序.我ocamlc在Linux Ubuntu 10.04下使用3.11.2版.我想编译两个文件:
a.ml
b.ml
Run Code Online (Sandbox Code Playgroud)
文件b.ml使用来自的定义a.ml.据我所知,我只能用于ocamlc -c编译.ocamlc当我有所有.cmo文件将它们链接到可执行文件时,我可以调用最后一次.此外,在编译使用另一个文件中的定义的文件时,我必须告诉编译器在哪个.cmi文件中查找外部定义.
所以我的想法是使用:
ocamlc -i -c a.ml > a.mli
ocamlc -c a.mli b.ml
ocamlc -o b a.cmo b.cmo
Run Code Online (Sandbox Code Playgroud)
第一步的工作和生产文件a.mli和a.cmo,但在运行第二步,当我得到
File "b.ml", line 1, characters 28-31:
Error: Unbound value foo
Run Code Online (Sandbox Code Playgroud)
where foo是在其中定义a.ml和调用的函数b.ml.
所以我的问题是:如何单独编译每个源文件并指定要在命令行上导入的接口?我一直在查看文档,据我所知,我必须指定.mli要包含的文件,但我不知道如何.
编辑
这里有更多细节.文件a.ml包含定义
let foo = 5;;
Run Code Online (Sandbox Code Playgroud)
文件b.ml包含表达式
print_string (string_of_int foo) ^ "\n";;
Run Code Online (Sandbox Code Playgroud)
真实的例子更大但是有了这些文件,我已经有了上面报告的错误.
编辑2
我已编辑文件b.ml并替换为foo,A.foo并且这有效(b.ml即使我有另一个编译错误,这个问题并不重要,foo也可见).我想.mli根据建议明确编写我自己的文件更清晰
如果你展示了不起作用的代码会更清楚.正如克里斯托弗指出的那样,最可能的问题是你没有指定哪个模块foo在哪里.你可以明确地指定模块,如A.foo.或者你可以open A只使用这个名字foo.
对于一个小例子并不重要,但对于一个大项目,你应该小心不要open太自由使用.你希望自由在你的模块中使用好的名字,如果你打开太多的名字,好名字可能会相互冲突.
首先解决unbound value问题,正如Jeffrey的回答所解释的那样.这是关于您正在使用的命令的注释.
通过几个步骤分解编译是了解正在发生的事情的好方法.如果你想编写自己的a.mli,最有可能隐藏模块的某些值A,那么你的命令ocaml -i -c a.ml > a.mli是获取该文件的第一个版本然后编辑它的好方法.但是如果你没有触摸a.mli,那么你不需要生成它:你也可以直接输入
ocamlc -o foo a.ml b.ml
Run Code Online (Sandbox Code Playgroud)
这将产生a.cmo,b.cmo和exectuable foo.
(它还将生成a.cmi,即a.mli通过发布获得的编译版本ocamlc -c a.mli.同样,它也将生成b.cmi).
请注意,顺序很重要:您需要在命令行a.ml之前提供b.ml.这样,在编译时b.ml,编译器已经看到a.ml并知道在哪里找到模块A.
还有一些评论:
A可用,但名称下A.foo.的内容a.ml一直没有复制粘贴到b.ml,相反,该模块的值A,在定义a.ml和它的编译版本a.cmo已被访问.A中b.ml,你可以通过任何之前在命令行中执行以下操作b.ml:
a.mli,将编译成 a.cmia.cmi如果你已经编a.mli入a.cmia.ml或者a.cmo如果您不需要编写自己的编译版本a.mli,即模块的默认接口是否A适合您.(这个界面只是每个值a.ml).