动态地在OCaml中实例化模块

时间:2015-05-25 13:56:44

标签: command-line module ocaml first-class

我有几个模块实现相同的接口。我想根据命令行中给出的一个参数只加载这个模块中的一个。

我正在考虑使用一流的模块,但问题是我想在模块实例化之前执行一些函数。

目前我有这个:

module Arch = (val RetrolixAbstractArch.get_arch() : RetrolixAbstractArch.AbstractArch)


let get_arch () =
  let arch = Options.get_arch() in
  if arch = "" then
    Error.global_error "During analysis of compiler's architecture"
               "No architecture specified"
  else
    if arch = "mips" then
      ( module MipsArch : AbstractArch)
    else
    Error.global_error "During analysis of compiler's architecture"
               (Printf.sprintf "Architecture %s not supported or unknown" arch)      

但由于命令行尚未解析,Options.get_arch会给我空字符串。

我想在执行此函数之前实现命令行解析(不在函数中添加解析)。可能吗 ?我应该找到其他方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:6)

这是可能的,但您必须使用本地模块。这是一个小问题,基本上只需要很少的重构。

let arch_of_name = function
  | "mips" -> (module MipsArch : AbstractArch)
  | "arm"  -> (module Arm)
  | _ -> invalid_arg "unknown arch"


let main () = 
  ...
  let arch_name = get_arch () in
  let module Arch = (val arch_of_name arch_name) in
  (* here you can use module Arch as usual *)

另一种方法是使用arch结构对模块进行编程,并在知道体系结构后立即实例化您的仿函数。您可以看到一个完整的示例here(请参阅为特定体系结构创建一流模块的函数target_of_arch)。

如果您的AbstractArch接口不包含类型定义,那么您可以使用其他抽象而不是模块:函数或对象的记录。它们可以更顺畅地工作,甚至可以让你动态地重载arch实例(通过使arch实例作为参考,虽然我不建议这样做,因为它是非常不洁净的,imo)。