Определить модуль и вызвать его функцию в одном файле
Я определил модуль в файле 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
Последний вариант короче, потому что вам не нужно указывать информацию о типе, но он более подвержен ошибкам, потому что компилятор не нагреет вас в случае частичного применения.