0

跑步

type expression =
    | Num of int
    | Var of string
    | Let of string * expression * expression
    | Binop of string * expression * expression;;

在一个 utop 会话中大约需要 8 秒。

现在,如果我们跳到一个单独的utop 会话并运行

type expression =
    | Num of int
    | Var of string
    | Let of string * expression * expression * expression * expression
    | Binop of string * expression * expression;;

这大约需要 13 秒。

最后,让我们在同一个会话中做这两个

type expression =
    | Num of int
    | Var of string
    | Let of string * expression * expression
    | Binop of string * expression * expression;;

type expression_1 =
    | Num of int
    | Var of string
    | Let of string * expression_1 * expression_1 * expression_1 * expression_1
    | Binop of string * expression_1 * expression_1;;

第一种和单独会话一样需要 8 秒,但之前的 13 秒操作现在是 3 秒!这里发生了什么?

我对 OCaml 对类型所做的所有工作知之甚少。也许它能够通过一些智能缓存从 2 表达式树构造 4 表达式树?

还是更精细的东西?

例如,由于我的自定义类型在这两种情况下都有递归组件,它是否检查是否expression_1expression具有某种“结构”相似性?随着编译器在程序中注释和统一类型,当它遇到新类型时可能有几个选项(不是双关语):它是否使用显式预定义的类型,这些类型被注释为推断手头类型的线索,还是它会遍历它知道的类型,然后是我定义的自定义类型?

编译器是否最初评估某种类型,然后提出一个表示来检查它是否是某种类型?在这个例子中,是不是将所有...的递归结构构造expression * expression成一棵树?

我真的不知道,但我想知道!

4

1 回答 1

3

在您的实验中,您测量的不是 OCaml,而是 utop,一个 OCaml 的交互式解释器。虽然您显示的数字确实令人发指且不寻常,但它们与 OCaml 性能无关。它们表明您的系统存在严重问题。

说到 OCaml,它具有一个非常高性能的编译器,能够每毫秒输入数千个表达式,所以你几乎不会注意到它。事实上,OCaml 经常被用作各种高级语言和定理证明器的目标语言,如 Coq、Ott 和 F*,因此它用于编译机器生成的代码,这种代码通常很多。

回到您的示例,我怀疑您要么在包含大量文件的文件夹中运行 utop,要么您的 .ocamlinit 文件运行缓慢的计算,或者您没有完整地向我们描述您的实验。或者你在 utop 中遇到了一些错误。

我还可以建议使用down新的 OCaml 顶级库。例如,(第一个符号是提示符)

$ ocaml
# #use "topfind";;
# #require "down";;

或者只是运行ocaml使用rlwrap,例如,

$ rlwrap ocaml

或者,甚至,在您的浏览器中尝试 OCaml 1

此外,当你想了解 OCaml 对你的类型定义做了什么时——没有什么复杂的东西只是解析它并执行一些健全性检查。即使在 30 年前,任何事情都可能需要不到一秒钟的时间。


1) )在这种情况下,OCaml 编译器本身被编译为 Javascript 并由您的浏览器运行,它仍然会在几毫秒内接受您的定义。

于 2019-08-21T01:45:40.930 回答