Определить модуль и вызвать его функцию в одном файле

Я определил модуль в файле mod.ml следующее:

module Area = struct
  ...
  let test : unit =
    Print.printf "haha"
  ...
end;;

Print.printf "hehe";;

Area.test

Кажется что без ;; после endЯ не могу скомпилировать код ocamlc, Но мне кажется странным иметь ;; в файле Ocaml, я должен держать их?

После генерации mod от ocamlcЗапускаю modпечатает hahahehe, Кажется, что haha печатается по определению let test : unit ... вместо его вызова Area.test, Что я кроме как в результате hehehaha или же hahahehehaha, Кто-нибудь может объяснить, почему это не то, что я ожидал?

2 ответа

Решение

Я никогда не пользуюсь ;; в моих исходных файлах я думаю об этом как о части интерфейса верхнего уровня. Для вашего кода я бы написал:

module Area = struct
  let test : unit -> unit =
      fun () -> Printf.printf "haha"
end

let () =
    Printf.printf "hehe";
    Area.test ()

Для чего это стоит, Area.test поскольку вы определили, что это не функция, это просто единичное значение с побочным эффектом во время его вычисления. В моем коде здесь я изменил его на функцию типа unit -> unit,

Когда ocamlc загружает модуль, он оценивает все определения "верхнего уровня" в том порядке, в котором они определены. В вашем случае у вас есть три определения "верхнего уровня".

  • Первое значение unit (единственное значение типа unit), который привязан к названию "тест". Это значение генерируется после побочного эффекта: отображение "хаха" (здесь модуль Area служит пространством имен, не задерживает вычисления);

  • Вторым является значение unit также, но без привязки к имени; Это значение также генерируется с побочным эффектом: отображение "хе-хе";

  • Последнее - это просто значение, связанное с именем "тест", т.е. unit, Однако на этот раз побочных эффектов нет, так как значение unit связанный с именем "тест" уже был сгенерирован.

Если вы хотите получить побочный эффект при каждом вызове test, вам нужно использовать функцию:

let test () =  Print.printf "haha"

И для ;; часть вашего вопроса. Они нужны анализатору, чтобы знать, когда заканчивается выражение. Есть и другие способы помочь парсеру, например:

let () = Print.printf "hehe"

Или просто:

let _ = Area.test

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

Другие вопросы по тегам