【问题标题】:OCaml: returning a function from the function identifier onlyOCaml:仅从函数标识符返回函数
【发布时间】:2011-03-11 00:25:24
【问题描述】:

我正在编写一个程序,它解析用某种虚构语言编写的脚本并使用该脚本进行一些计算。这种语言有一个特殊的结构,用于调用'a -> bool 类型的外部OCaml 函数。所以,在中间我们可能有的语言

blah blah function (foo 45) blah blah

我希望解析器使用构造函数,例如

OCamlFunction of ('a -> bool) * 'a

将该位解析为值

OCamlFunction (foo,45)

其中 'foo' 是用户必须在单独的 .ml 文件中提供的函数,解析器事先并不知道该函数;只有定义了“foo”的 OCaml 文件的名称才会在运行时传递给解析器。所以,我需要定义一个 string->('a->bool) 类型的函数,它接受某个函数的名称并返回该函数。

我的问题是:

(1) 我假设代码的动态加载应该使用DynLink.loadfile。这是要走的路吗?

(2) 如何从函数“foo”的标识符中获得访问权限? (这会带我去camlp5吗?)

【问题讨论】:

    标签: compiler-construction ocaml dynamic-loading camlp4


    【解决方案1】:

    您不能直接按名称加载函数,因为 OCaml 没有这种支持,loadfile 函数只是运行代码,它不提供对名称的访问。

    您需要在加载的代码使用的主程序中支持某种函数注册 API。所以加载的代码会做类似

    ParserEngine.register_function "foo" foo_impl
    

    您可以使用 Camlp{4,5} 自动生成此样板代码,或者您可以使用 register_functions 调用来将关联列表最小化。

    register_functions 然后会将函数存储在某种内部结构中,例如哈希表或可变关联列表,以供您的解析器代码访问。

    【讨论】:

    • 听起来不错!我没有想到提供函数的实际 ml 文件可以在编译器/解析器中调用寄存器函数。我知道 DynLink 仅用于加载代码。我建议 DynLink 用于加载实际函数的部分,然后您只需要通过 camlp5 从标识符中获取这些函数。但是函数注册机制实际上要简单得多,也很有意义。谢谢!
    【解决方案2】:

    另一种解决方案是将整个脚本放在引号中,并将每个 ocaml 值放在反引号中。例如,这可以用 Camlp4 完成,但有一点语法成本(<<>> 围绕您的代码,$$ 围绕 OCaml 值)。然后脚本的解析将在编译时运行,因此 OCaml 类型器本身可以检查您引用的 OCaml 值是否也已明确定义。此外,您可以获得更精细的类型控制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多