我的文件夹包含多个文件,这些文件按以下顺序编译:{{1}},global.ml
,zone.ml
,abs.ml
main.ml
包含所有文件的一些参考变量(例如global.ml
)。
在let g1 = ref 0
中有一个声明zone.ml
。
在let f = !g1
中,有abs.ml
,它将在运行时开始时由g1 := 5
运行,我认为它是main
的初始化真实的运行时环境。
稍后g1
将致电main
。奇怪的是,我意识到需要Zone.f
代替f = 0
。
您认为这种行为是正常的吗?如果是这样,我应该更改什么,以便将f = 5
的当前值考虑在内?
PS:也许一个解决方案是在!g1
中创建一个函数let f v = v
,然后让zone.ml
调用main
。但是我在Zone.f !g1
中有几个全局引用变量g1
,我希望它们对所有文件和函数都有效,而且我不想让它们参与到global.ml
的签名中。功能
答案 0 :(得分:6)
您基本上关注模块中顶级值的评估顺序。发生这种情况的顺序与您编译文件的顺序无关,而是与链接文件时出现的顺序无关。
如果您忽略模块边界,如果按照您给出的顺序链接文件,您拥有的是这样的:
let g1 = ref 0
let f = !g1
let () = g1 := 5
f
的值为0,应该不足为奇。
请注意,main
不一定是运行时发生的第一件事。顶级值按链接它们时文件显示的顺序进行评估。通常,main
是最后发生的最后事件(因为它的文件通常是最后一个)。
(另请注意,拥有main
只是一个惯例,可能是像我这样的前C程序员所采用的。没有要求有一个名为main
的函数.OCaml只是评估顶部 - 级别值按顺序。)
修改强>
很难说如何在不了解更多代码的情况下重构代码。问题的实质似乎是您将f
定义为zone.ml
中的顶级不可变值,但您希望其值遵循g1
,这是一个可变值。
最简单的建议是从f
中移除zone.ml
的定义,并使用!g1
将其替换为文件中的任何位置。
如果要在f
的顶级保留名称zone.ml
,则必须将其重新定义为不可变值之外的其他值。功能是最明显的选择:
let f () = !g1
然后,您将f
替换zone.ml
中对f ()
的使用。