为什么在OCaml中“引用未定义的全局`Moduletest'”?

时间:2014-12-01 21:23:07

标签: functional-programming ocaml

我写了

let fact x = 
let result = ref 1 in
for i = 1 to x do
    result := !result * i;
    Printf.printf "%d %d %d\n" x i !result;
done;
!result;;

在名为“Moduletest.ml”的文件中,

val fact : int -> int

在名为“Moduletest.mli”的文件中。

但是,他们为什么不工作?

当我尝试在ocaml中使用时,

Moduletest.fact 3
它告诉我:

Error: Reference to undefined global `Moduletest'

发生了什么事?

感谢。

2 个答案:

答案 0 :(得分:8)

OCaml toplevel仅与标准库链接。关于如何使其他代码可见的几个选项:

  1. 的复制粘贴
  2. 从编辑评估
  3. 加载文件#use指令
  4. 制作自定义顶层
  5. 使用ocamlfind加载
  6. 的复制粘贴

    这种自我描述,您只需从某些来源复制代码并将其粘贴到顶层。不要忘记,在您添加;;

    之前,不会评估您的代码

    从编辑器

    进行评估

    当编辑器当然是Emacs ......嗯,确实它可以是任何其他有能力的编辑器,例如vim。此方法是前面的详细说明,其中编辑器实际上负责为您复制和粘贴代码。在Emacs中,您可以使用C-c C-b命令评估整个文件,或者可以使用C-c C-r将其缩小到选定区域,最精细的是使用C-c C-e,即评估表达式。虽然它有点马车。

    使用#use指令加载。

    该指令接受文件名,它实质上将复制并粘贴文件中的代码。请注意,它不会为您创建文件模块/例如,如果您的文件test.ml包含此内容:

    (* file test.ml *)
    let sum x y = x + y 
    

    然后使用#use指令加载它,实际上会为您的范围带来sum值:

    # #use "test.ml";;
    # let z = sum 2 2
    

    您无法使用sum来限定Test.,因为实际上并未创建Test个模块。 #use指令仅将文件的内容复制到顶层。没什么。

    制作自定义顶层

    您可以使用编译的代码创建自己的顶层。这是一个高级主题,所以我将跳过它。

    使用ocamlfind

    加载库

    ocamlfind是一个工具,允许您查找并加载系统上安装的库到您的顶层。默认情况下,toplevel不与标准库以外的任何代码链接。甚至,并非库的所有部分都实际链接,例如,Unix模块不可用,并且需要显式加载。有原始指令可以加载任何库,例如#load#include,但它们不适合临时用户,特别是如果您有优秀的ocamlfind可供使用。在使用它之前,您需要加载它,因为它在默认情况下也不可用。以下命令将加载ocamlfind并添加一些新指令:

    # #use "topfind";;
    

    在加载过程中,它会向您显示如何使用它的一些提示。最有趣的指令是#require。它接受一个库名,并将其代码加载(即链接)到顶层:

    # #require "unix";;
    

    这将加载unix库。如果您不确定,关于库的名称,您始终可以使用#list命令查看所有库。 #require指令很聪明,它会自动加载库的所有依赖项。

    如果您不希望每次启动OCaml顶级时都键入所有这些指令,那么您可以在主目录中创建.ocamlinit文件,然后将其放在那里。该文件将在顶级启动时自动加载。

答案 1 :(得分:0)

我已经测试了你的代码,它看起来很好。您应该通过以下方式从OCaml toplevel(从.ml.mli文件的同一目录启动)“加载”它:

# #use "Moduletest.ml";;
val fact : int -> int = <fun>
# fact 4;;
4 1 1
4 2 2
4 3 6
4 4 24
- : int = 24