在顶层ocaml
或ghci
顶层工作时,我经常为需要更好的词、绑定值、函数、加载的模块等建立重要的“上下文”。有没有办法保存所有这些并在以后重新加载,这样我就可以从我离开的地方继续?或者更好的是,将整个文件作为文本文件转储出来,可以重新加载或修改成可以编译成可执行文件的代码(例如,通过添加 Main)?
6 回答
HOL light的用户也有类似的需求,他们使用检查点程序来保存顶层的快照。请参阅caml 邮件列表或本 HOL 教程的第 8 页上的此消息。
一般来说,最好将定义保留为源代码,而不是二进制顶级快照。许多工具允许将 .ml 文件快速加载到顶层以便于实验(emacs 模式等)。请参阅 HOL 教程中的警告:
在 HOL 中开发大型证明时,您应该始终将证明脚本作为 OCaml 文件准备好重新加载,而不是依赖 ckpt。这将允许稍后修改证明,供其他人使用等。但是,制作中间快照非常方便,因此您不必加载大文件来进一步处理证明。这类似于编程中的常见情况:您应该始终保留完整的源代码,但不希望每次使用代码时都重新编译所有源代码。
至少在 OCaml 中没有对此的内置支持。解决方案是使用rlwrap或任何其他 readline 包装器将您的输入历史记录到文件中。例如 :
> rlwrap -H mysession.ml ocaml
缺点是这也会记录有语法错误的输入,所以你必须清除它。请注意,如果您在没有 -H 选项的情况下调用它,默认情况下 rlwrap 会自动将您的输入保存在 ~/.ocaml_history 中。
在 Haskell 中,只需使用:e file
. 这将打开标准编辑器并让您编辑一些文件。之后,使用:r
重新加载它。它将自动重新编译。
请注意,在此之后,您所有的“临时”定义的功能都将丢失。有关更多信息,请参阅文档。
ghci
将haskeline用于命令行输入历史记录,因此您可以向上滚动以重复/编辑输入。您的输入历史记录通常记录在一个文件中,您可以ghci_history
在给出的目录中找到该文件
System.Directory.getAppUserDataDirectory "ghc"
有各种命令可以探索“上下文”(:show bindings、:show modules、:def、..),但它们的输出不足以重现您的会话(尽管无论如何都值得了解它们)。
一般来说,将会ghci
话与打开的编辑器窗口结合起来的建议是合理的:如果它不仅仅是一个一次性定义,即使只是出于调试目的,最好将其包含在要加载到的模块中ghci
,以便您可以重用它.
ghci
哦,如果“上下文”是指要加载的一些默认设置或模块,则在每个项目的基础上,还有配置文件。也方便定义自己的ghci
命令。
在 ocaml 中,您可以构建自己的顶层。它至少解决了加载模块的问题。
http://caml.inria.fr/pub/docs/manual-ocaml/toplevel.html#sec278
ocamlmktop 命令构建包含在启动时预加载的用户代码的 OCaml 顶层。
ocamlmktop 命令将一组 .cmo 和 .cma 文件作为参数,并将它们与实现 OCaml 顶层的目标文件链接起来。典型的用途是:
ocamlmktop -o mytoplevel foo.cmo bar.cmo gee.cmo
这将创建字节码文件 mytoplevel,其中包含 OCaml 顶层系统,以及来自三个 .cmo 文件的代码。此顶层是直接可执行的,并由以下方式启动:
./mytoplevel
这进入了一个常规的顶层循环,除了来自 foo.cmo、bar.cmo 和 gee.cmo 的代码已经加载到内存中,就像你输入了:
#load "foo.cmo";; #load "bar.cmo";; #load "gee.cmo";;
在顶层入口处。但是,模块 Foo、Bar 和 Gee 没有打开;你还得做
open Foo;;
你自己,如果这是你想要的。
这也一直困扰着我,所以我写了一个快速的 python/expect脚本来在每个 ghci 会话开始时重播 ghci_history。
它不是很抛光。例如,它总是重播整个历史,这可能会很慢。