2014-01-13 2 views
4

В моем коде у меня есть module M = Implementation1, а затем я ссылаюсь на M, а не на Implementation1. Проблема в том, что я должен перекомпилировать свою программу, чтобы изменить Implementation1 на Implementation2. Я хотел бы контролировать, какую реализацию использовать с параметром командной строки. Это возможно?Выбор какого модуля ocaml для использования с параметром командной строки

Простая ситуация, когда все реализации имеют общую подпись?

+4

Ваш вопрос недостаточно ясен. Вы имеете дело только с двумя известными статическими реализациями, и в этом случае вы должны искать [модули первого класса] (http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc81), или с реализациями, которые могут быть добавлены позже, и в этом случае вам нужно искать [динамическое связывание] (http://caml.inria.fr/pub/docs/manual-ocaml/libref/Dynlink.html). –

+0

У меня две реализации, известные статически. – pbp

ответ

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() 
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 вы можете использовать модули первого класса и выражение типа,

module Choose = (val (if use_impl1 then (module Impl_1) else (module Impl_2)) : IMP) 

использовать, если заявление, чтобы выбрать модуль, как определяется use_impl1 стоимость.

Смежные вопросы