5

我是 Ocaml 的新手,正在尝试编写一些小型示例应用程序。我ocamlc在 Linux Ubuntu 10.04 下使用 3.11.2 版本。我想编译两个文件:

a.ml
b.ml

文件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

第一步工作并生成文件a.mlia.cmo,但是在运行第二步时我得到

File "b.ml", line 1, characters 28-31:
Error: Unbound value foo

wherefoo是在 中定义a.ml和调用的函数b.ml

所以我的问题是:如何分别编译每个源文件并在命令行中指定要导入的接口?我一直在查看文档,据我所知,我必须指定.mli要包含的文件,但我不知道如何。

编辑

这里有更多细节。文件a.ml包含定义

let foo = 5;;

文件b.ml包含表达式

print_string (string_of_int foo) ^ "\n";;

真实的例子更大,但是有了这些文件,我已经有了上面报告的错误。

编辑 2

我已经编辑了文件b.ml并替换foo为并且这有效(即使我有另一个对这个问题并不重要的编译错误,A.foofoo 也是可见的)。b.ml我想.mli明确地编写我自己的文件会更干净,正如所建议的那样

4

2 回答 2

5

如果您显示不起作用的代码会更清楚。不过,正如 Kristopher 指出的那样,最可能的问题是您没有指定哪个模块foo在其中。您可以明确指定模块,如A.foo. 或者您可以open A并且只使用名称foo

对于一个小例子没关系,但对于一个大项目你应该注意不要open太随意使用。您希望在模块中自由使用好名称,如果打开太多模块,好名称可能会相互冲突。

于 2012-10-07T18:49:35.097 回答
5

首先解决unbound value问题,正如杰弗里的回答所解释的那样。这是关于您正在使用的命令的评论。

分几个步骤分解编译是了解正在发生的事情的好方法。如果您想编写自己的a.mli,很可能隐藏模块的某些值A,那么您的命令ocaml -i -c a.ml > a.mli是获取此文件的第一个版本然后编辑它的好方法。但是如果你不碰a.mli,那么你就不需要生成它:你也可以直接输入

ocamlc -o foo a.ml b.ml

这将产生a.cmo,b.cmo和可执行文件foo.

(它还将生成,这是您通过发布 获得a.cmi的编译版本。同样,它也会生成)。a.mliocamlc -c a.mlib.cmi

请注意,顺序很重要:您需要在命令行上提供a.mlbefore 。b.ml这样,在编译时b.ml,编译器已经看到a.ml并知道在哪里可以找到模块A


还有一些评论:

  • 您在“据我所知”段落中是对的。
  • 你并没有真正包含一个单独的文件,它更像是 Python 中的import:module 的值A是可用的,但是在 name 下A.foo。的内容a.ml没有被复制粘贴到b.ml中,而是模块的值A,定义在a.ml其中,它的编译版本a.cmo已被访问。
  • 如果您在 中使用此模块Ab.ml则可以在命令行之前传递以下任何内容b.ml
    • a.mli, 这将被编译成a.cmi
    • a.cmi如果你已经编译a.mlia.cmi
    • a.ml或者它的编译版本a.cmo,如果你不需要编写你自己的a.mli,即如果模块的默认接口A适合你。(这个接口就是 的每个值a.ml)。
于 2012-10-07T19:08:11.803 回答