在我的代码中,我module M = Implementation1
,然后我引用M
,而不是Implementation1
。问题是,我要重新编译我的程序,将Implementation1
更改为Implementation2
。我想通过命令行参数控制要使用的实现。这可能吗?
当所有实现共享签名时,情况是否更简单?
答案 0 :(得分:7)
由于两个实现都是静态已知的,因此您可以使用first class modules。关于如何构建程序有很多不同的可能性,这里有一个最小化顶层参考单元和最有效的语句:
module type M = sig
val test : unit -> unit
end
module M1 : M = struct
let test () = Printf.printf "Implementation 1\n%!"
end
module M2 : M = struct
let test () = Printf.printf "Implementation 2\n%!"
end
let test m =
let module M = (val m : M) in
(* If other modules of your program depend on the implementation of
M, functorize them over sig M and instantiate them with M here. *)
M.test ()
let main () =
let exec = Filename.basename Sys.executable_name in
let usage = Printf.sprintf
"Usage: %s [OPTION]...\n\
Program synopsis.\n\
Options:" exec
in
let m = ref (module M1 : M) in
let options = [
"-m1", Arg.Unit (fun () -> m := (module M1 : M)),
" Use implementation 1 (default)";
"-m2", Arg.Unit (fun () -> m := (module M2 : M)),
" Use implementation 2"; ]
in
let anon _ = raise (Arg.Bad "no positional argument supported") in
Arg.parse (Arg.align options) anon usage;
test !m
let () = main ()
答案 1 :(得分:2)
对于大多数版本的OCaml,您可以使用camlp4执行此操作。
IFDEF USE_IMP1 THEN
module M = Implementation1
ELSE
module M = Implementation2
END
然后传递如下所示的预处理选项将选择要在构建中合并的正确选项。
-pp "camlp4of -UUSE_IMP1" //to undefine USE_IMP1
-pp "camlp4of -DUSE_IMP1" //to define USE_IMP2
对于OCaml> = 4.00.0的版本,您可以使用First-Class模块和类似的表达式
module Choose = (val (if use_impl1 then (module Impl_1) else (module Impl_2)) : IMP)
使用if语句选择由use_impl1
值确定的模块。