有趣的问题,最明显的方法是创建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
所以现在的问题是,为什么这不起作用
如果我们看一下Value Bindings部分,在脚注 25 的The Definition of Standard ML (Revised) 的第 42 页上,
它说
(25) When the option is present we have Dom VE ∩ Dom VE′ = ∅ by the syntactic restrictions.
因此,虽然and
for 函数允许相互递归,但and
for values 允许确保值环境是不相交的。
唉,我不知道如何在不提升函数值的情况下做到这一点。