3

同じインターフェースを実装するモジュールがいくつかあります。コマンド ラインで指定された 1 つの引数に応じて、このモジュールを 1 つだけロードしたいと考えています。

私はファーストクラスのモジュールを使用することを考えていましたが、問題はモジュールがインスタンス化される前にいくつかの関数を実行したいということです.

今のところ私はこれを持っています:

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ため、空の文字列を渡してください。

この関数が実行される前に、コマンドラインの解析を実現したいと思います(関数に解析を追加することなく)。出来ますか ?これを達成する別の方法を見つける必要がありますか?

4

1 に答える 1

9

可能ですが、ローカル モジュールを使用する必要があります。これはマイナーな問題であり、基本的にリファクタリングはほとんど必要ありません。

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 *)

もう 1 つのアプローチは、アーキテクチャを理解したらすぐにモジュールをアーキテクチャ構造でファンクタ化し、ファンクタをインスタンス化することです。ここで本格的な例を見ることができます(target_of_arch特定のアーキテクチャのファーストクラス モジュールを作成する関数を参照してください)。

AbstractArchインターフェイスに型定義が含まれていない場合は、モジュールの代わりに他の抽象化 (関数またはオブジェクトのレコード) を使用できます。それらはよりスムーズに動作する可能性があり、arch インスタンスを動的にオーバーロードすることさえ可能にする場合があります (archインスタンスを参照にすることにより、これは非常に汚れているためお勧めしませんが、imo)。

于 2015-05-25T15:06:24.280 に答える