在标准ML中,如何定义函数和值取决于彼此?
以下节目:
val cmds = [("help", cmd_help)];
fun cmd_help () = List.app (fn cmd => print (#1 cmd ^ "\n")) cmds;
cmd_help ();不编译:
$ mlton example.sml
Error: example.sml 1.22-1.29.
Undefined variable: cmd_help.是否有可能对cmds和cmd_help进行定义,使它们彼此了解,并将其作为顶级定义公开给程序的其他部分?
发布于 2020-08-16 11:01:43
有趣的问题是,最明显的方法是使cmds成为一个酉函数,然后在cmd_help中调用它,就像普通的一对递归函数一样。
fun cmds () = [("help", cmd_help)]
and cmd_help () = List.app (fn cmd => print ((#1 cmd) ^ "\n")) (cmds ());
cmd_help ();人们可能会认为,您可以扭转这种情况,将cmds_help视为一个值。实际上,语法甚至看起来是解析的。
val a = ()
and b = fn () => ()但是,当您将相互递归添加到工作中时,它实际上并不编译(我使用MLton和smlnj尝试了下面的内容)。手动声明类型,因为推断做得不是很好。
val cmds_v : (string * (unit -> unit)) list = [("help", cmd_help_v)]
and cmd_help_v : unit -> unit = fn () => List.app (fn (cmd: string * (unit -> unit)) => print ((#1 cmd) ^ "\n")) (cmds_v);最后一个案例的结果是:
错误:未绑定变量或构造函数: cmds_v 错误:未绑定变量或构造函数: cmd_help_v
所以现在的问题是,如果我们看一下标准ML的定义(修订)脚注25中第42页的值绑定,为什么这个方法不能工作呢?
(25)当选项存在时,由于语法限制,我们有Dom、VE、∩、Dom、VE‘=∅。
因此,虽然函数的and允许相互递归,但是值的and允许确保值环境是不相交的。
唉,我不知道在不将值提升到函数的情况下如何做到这一点。
发布于 2021-01-08 22:36:56
我认为最好的解决方案是将函数封装在ref访问中,如下所示:
val cmd_help_ref : (unit -> unit) ref
= ref (fn _ => raise Fail "cmd_help not bound");
fun cmd_help () = !cmd_help_ref ();
val cmds = [("help", cmd_help)];
cmd_help_ref := fn () => List.app (fn cmd => print (#1 cmd ^ "\n")) cmds;
cmd_help ();https://stackoverflow.com/questions/63428214
复制相似问题