2015-05-25 94 views
2

我有幾個模塊實現相同的接口。我只想根據命令行中給出的一個參數加載這個模塊中的一個。動態實例化OCaml中的模塊

我在想使用一流的模塊,但問題是我想在模塊實例化之前執行一些功能。

目前我有這樣的:

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給我空字符串。

我想在執行此函數之前實現命令行解析(不添加函數中的解析)。可能嗎 ?我是否應該找到其他方法來實現這一目標?

+0

什麼是「選項」,你爲什麼不在調用這個(整個問題的)模塊的get_arch之前調用命令行解析器? – antron

+0

我的問題是函數get_arch在主函數之前調用。所以此時不​​調用命令行解析器。但將其稱爲兩次會很奇怪。選項是存儲程序選項變量的模塊,取決於命令行的變量。 – Saroupille

+0

爲什麼在主函數之前調用get_arch?它是模塊初始化的一部分嗎?你可以重新排列它,以便你有其他的主函數,它允許你控制調用順序,包括命令行解析器,get_arch和你當前的主函數。 – antron

回答

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

另一種方法是拱結構functorize你的模塊,並儘快實例化函子,你知道的架構。您可以看到一個完整的示例here(請參見功能target_of_arch,它爲特定體系結構創建一流模塊)。

如果您的AbstractArch接口不包含類型定義,那麼您可以使用其他抽象而不是模塊:函數或對象的記錄。他們可能會更順利地工作,甚至可能允許您動態重載拱實例(通過將arch實例作爲參考,儘管我不建議這樣做,因爲它是非常不清潔的,imo)。