Functional programming 为什么;引用未定义的全局“Moduletest'&引用;用OCaml?

Functional programming 为什么;引用未定义的全局“Moduletest'&引用;用OCaml?,functional-programming,ocaml,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”的文件中 在名为“Moduletest.mli”的文件中 但是,他们为什么不工作呢 当我尝试在ocaml中使用时 Moduletest.fact 3 它告诉我: Error

我写

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”的文件中

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

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

当我尝试在ocaml中使用时

Moduletest.fact 3
它告诉我:

Error: Reference to undefined global `Moduletest'
发生了什么事


谢谢。

我已经测试了你的代码,看起来不错。您应该通过以下方式从OCaml顶层“加载”它(从与
.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
##使用“Moduletest.ml”;;
val事实:int->int=
#事实4;;
4 1 1
4 2 2
4 3 6
4 4 24
-:int=24

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

  • 复制粘贴
  • 编辑的评价
  • 加载文件
    #使用
    指令
  • 定制顶级
  • 使用ocamlfind加载
  • 复制粘贴 这种自我描述,您只需从某些源代码复制代码并将其粘贴到顶级。不要忘记,在添加
    ;之前,toplevel不会对代码求值

    编辑的评价 编辑当然是Emacs。。。实际上,它可以是任何其他有能力的编辑器,比如vim。此方法是前一种方法的精化,编辑器实际上负责为您复制和粘贴代码。在Emacs中,您可以使用
    C-C-b
    命令对整个文件求值,也可以使用
    C-C-r
    将其缩小到选定区域,最精确的方法是使用
    C-C-e
    ,即对表达式求值。虽然它有点车

    使用
    指令加载。
    这个指令接受一个文件名,它将从文件中复制并粘贴代码。请注意,它不会为您创建文件模块/例如,如果您有包含以下内容的文件
    test.ml

    (* file test.ml *)
    let sum x y = x + y 
    
    然后用
    #use
    指令加载它,实际上会将
    sum
    值带入您的范围:

    # #use "test.ml";;
    # let z = sum 2 2
    
    您不能使用
    Test.
    来限定
    sum
    ,因为实际上没有创建
    Test
    模块
    #use
    指令仅将文件内容复制到顶层。没别的了

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

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

    # #use "topfind";;
    
    在加载过程中,它将向您展示如何使用它的一些提示。添加的最有趣的指令是
    #require
    。它接受库名称,并将其代码加载(即链接)到顶级:

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


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

    您是如何“在ocaml中使用”的?使用
    #使用
    #加载
    或从其他文件加载?你是怎么编译的?您的代码似乎没有任何问题。我假设您使用的是
    #use
    ,这只是将文件的内容输入顶层,因此没有周围的隐式模块名(按文件)。我的教授告诉我应该在cmd或terminal:ocaml moduletest.cmo中编译和编写。最后,我发现它可以工作。是的,除了交互式顶层,OCaml还有一个编译器=)
    # #require "unix";;