Создавать модуль в 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
дай мне пустую строку.
Я хотел бы реализовать синтаксический анализ командной строки до того, как эта функция будет выполнена (без добавления синтаксического анализа в функцию). Является ли это возможным? Должен ли я найти другой способ добиться этого?
1 ответ
Это возможно, но вы должны использовать локальные модули. Это небольшая проблема, которая требует лишь небольшого количества рефакторинга.
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 *)
Другой подход состоит в том, чтобы функторизовать ваши модули с арочной структурой и создать ваши функторы, как только вы узнаете архитектуру. Вы можете увидеть полноценный пример здесь (см. Функцию target_of_arch
это создает первоклассный модуль для конкретной архитектуры).
Если твой AbstractArch
Интерфейс не содержит определения типов, тогда вы можете использовать другие абстракции вместо модулей: записи функций или объектов. Они могут работать более плавно и даже могут позволить вам динамически перегрузить экземпляр arch (сделав arch
пример, чтобы быть ссылкой, хотя я бы не предложил это, так как это довольно нечисто, IMO).