我喜欢OCaml,我正在等待我的Real World OCaml副本!我是初学OCaml程序员,只知道功能部分,有点必要,但对模块,仿函数,对象等并不多...
对于某种翻译项目,我做了类似新手emacs的评估.我保留一个三元组列表,其中包含一个命令名绑定列表作为字符串,一个描述字符串和要调用的ocaml函数.主循环只查找列表中的匹配条目并调用该函数.
然后,它是非常简单的添加新functionnalities,你只写一个函数,并把在列表中的条目.
我喜欢像Emacs这样可自我扩展的概念,这很容易扩展,但不能真正自我扩展.
我可以使用OCaml自行扩展程序吗?我该怎么办?
我知道Emacs是如何工作的,它是一个很大的虚拟机,因此它可以解释代码并自行修改它的运行时环境,但有没有办法通过用户添加的模块为OCaml程序添加功能?或者是其他东西 ?
ps:如果我的项目听起来很基本但我是初学者,请不要嘲笑我!
谢谢
另一种解决方案可能是使用Ocaml 动态加载工具,例如Dynlink模块.每个动态加载的共享模块可以例如将条目添加到某些全局哈希表映射字符串名称到函数(相同类型)等等.这个初始化 - 运行动态加载模块的顶层表达式 - 在其加载时发生(当你打电话时Dynlink.loadfile),有点像_initPOSIX 的旧功能dlopen
例如,您可以让程序在运行时发出一些Ocaml代码; 叉它的一个汇编成可加载的动态库使用ocamlopt -shared ; 然后Dynlink.loadfile该库.该库的初始化部分将使用主程序中提供的某些适当功能来注册闭包.
或者,在Ocaml中编写(或使用)某些虚拟机或解释器.
您也可以使用一些JIT库,例如Ollvm,并生成一些类似C的代码(可能dlopen在主程序的某些C粘合代码中使用).
但正如Simon Shine回答的那样,MetaOcaml可能是更好的方式.
BTW,也许您想要一些Common Lisp实现?
(未经测试的代码!一些细节可能是错误的)
你的主程序prog.ml将包含
let ht = Hashtbl.create 53;;
let add_name_fun (name : string) (f : int -> int) =
Hashtbl.add ht name f;;
(* here you might emit the 'plugin.ml' file and fork its compilation *)
Dynlink.loadfile "plugin.cmxs";;
(* as an example we apply every added name & function to 3 *)
Hashtbl.iter ht (fun n f) -> Printf.printf "n=%s (f 3)=%d\n" n (f 3);;
Run Code Online (Sandbox Code Playgroud)
你的prog.mli包含:
val : add_name_fun : string -> (int -> int) -> unit;;
Run Code Online (Sandbox Code Playgroud)
你plugin.ml会包含
Prog.add_name_fun "foo" (fun x -> x+3);;
Run Code Online (Sandbox Code Playgroud)
但我没有测试代码.
PS.在POSIX系统上,您可以使用dlopen和dlsym在C中执行类似的操作.我的GCC MELT是做那个.另请参见本.
注意:如果您喜欢元编程方法,请阅读J.Pitrat的博客和书籍.
| 归档时间: |
|
| 查看次数: |
170 次 |
| 最近记录: |