我写了
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'
发生了什么事?
感谢。
答案 0 :(得分:8)
OCaml toplevel仅与标准库链接。关于如何使其他代码可见的几个选项:
#use
指令这种自我描述,您只需从某些来源复制代码并将其粘贴到顶层。不要忘记,在您添加;;
当编辑器当然是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