Перекрестное соединение OCaml

как делает работу соединения, на которую ссылаются, в OCaml?

Пример, давайте предположим, что у меня есть 3 модуля, объявленные как

  • A.ml
  • B.ml
  • C.ml

из которых

  • A потребности B и C
  • B потребности A

Как я должен продолжить двигаться в компиляции?

Так как порядок является соответствующим использованием ocamlc или ocamlopt как я могу зафиксировать перекрестную ссылку между B и A?

Я пытаюсь сначала скомпилировать их всех в .cmo с ocamlc -c и затем соедините, все они, но без успеха начиная со свопинга аргументов просто переместят проблему от модуля до другого.

Определенная ошибка:

Ошибка: Ошибка при соединении A.cmo: Ссылка на неопределенный глобальный 'B'

(или наоборот, если я подкачиваю порядок args),

Я думаю, что это - легкий вопрос, но я не могу решить его..заранее спасибо

6
задан nlucaroni 1 July 2010 в 17:14
поделиться

2 ответа

Вы должны объединить модули в один файл и сделать их рекурсивными . Я не верю, что есть способ сделать это в процессе компиляции двух отдельных файлов.

module rec A : 
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (B.g x) + 1
        let g x = x + 1
    end
and B :
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (A.g x) + 1
        let g x = x + 1
    end

РЕДАКТИРОВАТЬ: Судя по вашему комментарию, я предполагаю, что у вас есть определение типа парсера и функции, которые обрабатывают / работают с типом в том же файле. Я согласен с вами, в этом есть смысл. Но, как вы уже испытали, если этот файл должен не только работать с типом, но и вызывать синтаксический анализатор для создания данных, как синтаксический анализатор собирается его построить? Мое решение заключалось в том, чтобы выделить тип в отдельный модуль и открыть этот модуль в модуле, выполняющем операции.

Таким образом, вы разбиваете A на ( A и A '), где A' содержит тип, созданный B , и используется в A . Ваши зависимости становятся:

  • A требует A ' и B и C
  • B требует A'

Для Например, у меня есть синтаксический анализатор файлов конфигурации, который я использую для запуска любого написанного мной приложения.

 ConfType - содержит тип t
Conf - вызывает парсер и содержит вспомогательные функции для типа ConfType.t
ConfParser - для ocamlyacc
ConfLexer - для ocamllex

Альтернативой всему этому является использование полиморфных вариантов. Таким образом вы удаляете зависимости, поскольку они определены специально. Конечно, тип, созданный синтаксическим анализатором, может отличаться от типа в Conf, и компилятор не сможет помочь вам с ошибкой.

7
ответ дан 10 December 2019 в 00:32
поделиться

Язык Ocaml поддерживает рекурсию между модулями, но компилятор не поддерживает рекурсию между компиляциями. единицы. Таким образом, у вас не может быть A.ml , требующего B.ml , и B.ml , требующего A.ml . Рефакторинг для удаления рекурсии лучше всего, если вы можете сделать это легко, но давайте предположим, что вы не можете.

Одно из решений, как объяснил nlucaroni, состоит в том, чтобы собрать оба модуля в один файл и использовать module rec . Другое решение иногда состоит в том, чтобы превратить один модуль в функтор, например, превратить A в функтор F , который принимает аргумент с подписью B , и скомпилировать сначала файл, определяющий F , затем B , затем файл, который просто определяет модуль A = F (B) .

Ocamlyacc действительно все усложняет, но вы можете обмануть его! Вы можете написать module A = functor (...) -> struct в заголовке .mly и соответствующий end в нижнем колонтитуле. Однако вам придется переписать сгенерированный .mli , чтобы добавить модуль A: functor (...) -> sig и end как часть вашей сборки процесс.(Я знаю, что делал это раньше, чтобы решить ту же проблему, что и у вас, но я не помню, где, поэтому не могу привести пример из реальной жизни.)

Еще одна возможность, которую стоит изучить, - это переход с Ocamlyacc to Menhir , который представляет собой замену Ocamlyacc (практически не требует переноса, поскольку синтаксис такой же) с некоторыми полезными функциями, которые могут вам помочь, например, поддержка параметризованных модулей синтаксического анализатора (то есть функторов).

3
ответ дан 10 December 2019 в 00:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: