OCaml:仅从函数标识符返回函数
我正在编写一个程序,它解析用某种编写的语言编写的脚本,并使用该脚本进行一些计算。该语言有一个特殊的构造,用于调用 'a ->; 类型的外部 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 吗?)
I am writing a program which parses scripts written in some made-up language and does some computations using that script. This language has a particular construct which is used to call external OCaml functions of the type 'a -> bool
. So, in the middle of the language we may have
blah blah function (foo 45) blah blah
and I'd like the parser to use a constructor such as
OCamlFunction of ('a -> bool) * 'a
to parse that bit as the value
OCamlFunction (foo,45)
where 'foo' is a function that the user will have to provide in a separate .ml file and which the parser doesn't know beforehand; only the name of the OCaml file where "foo" is defined is passed to the parser at runtime. So, I need to define a function of type string->('a->bool)
which takes the name of some function and returns that function.
My questions are:
(1) I'm assuming that the dynamic loading of code should use DynLink.loadfile. Is this the way to go?
(2) How do I get access to the function "foo" from the knowledge of its identifier? (Will this lead me to camlp5?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您不能直接按名称加载函数,因为 OCaml 没有这种支持,并且 loadfile 函数仅运行代码,它不提供对名称的访问。
您需要在主程序中支持加载代码使用的某种函数注册 API。因此,加载的代码将执行类似的操作,
您可以使用 Camlp{4,5} 来自动生成此样板代码,或者您可以进行
register_functions
调用,该调用采用关联列表来最小化它。然后,
register_functions
会将函数存储在某种内部结构中,例如哈希表或可变关联列表,以供解析器代码访问。You cannot, directly, load a function by name, as OCaml does not have that kind of support and the
loadfile
function just runs the code, it does not provide access to names.You need to support some kind of function registration API in your main program that is used by the loaded code. So the loaded code would do something like
You could use Camlp{4,5} to automate this boilerplate code generation, or you could have a
register_functions
call that takes an association list to minimize it.register_functions
would then store the functions in some internal structure like a hash table or mutable association list, ready for your parser code to access.另一种解决方案是将整个脚本放在引号中,并将每个 ocaml 值放在反引号中。例如,这可以使用 Camlp4 来完成,但会产生轻微的语法成本(代码周围的
<<
>>
,$
OCaml 值周围的$
)。然后,脚本的解析将在编译时运行,因此 OCaml 类型器本身可以检查您引用的 OCaml 值是否定义良好。此外,您还可以获得更精细的类型控制。Another solution would be to place the whole script in a quotation, and put each ocaml value inside in an antiquotation. This can be done with Camlp4 for example, but has a slight syntactic cost (
<<
>>
around your code,$
$
around OCaml values). The parsing of the script would then run at compile-time, so the OCaml typer itself could check that the OCaml values you refer too are well defined. In addition, you get finer type control.