Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Статически типизированные языки обычно вынуждают писать типы переменных по любому поводу. Но уже далеко не всегда: теория и практика языков программирования значительно ушли вперед, просто эти достижения не сразу принимаются индустрией. Сегодня мы рассмотрим язык OCaml и увидим, что статическая типизация необязательно связана с неудобствами.
OCaml относится к семейству языков ML. К нему же относятся ныне редкий Standard ML, Microsoft F#, который во многом представляет собой клон OCaml, и, с оговорками, Haskell.
Многие языки семейства ML способны производить статическую проверку типов в коде, где нет ни одного объявления типа переменной благодаря механизму вывода типов. Ограниченную форму вывода типов многие уже видели в Go, где можно не объявлять примитивные типы, а просто писать var x = 10
. Swift предоставляет те же возможности. OCaml идет гораздо дальше и выводит типы функций.
let sqr x = x * x (* sqr : int -> int *)
Теоретическая основа вывода типов — алгоритм Хиндли — Милнера. Детерминированный вывод типов возможен не во всех системах. В частности, Haskell использует тот же подход, но функции в нем требуют явного объявления типа. Цена детерминированности — отсутствие полиморфизма ad hoc (перегрузки функций). Каждая функция в OCaml может иметь один и только один тип. Отсутствие перегрузки функций компенсируется «функторами» — параметризованными модулями.
Swift заимствовал многие концепции из ML, в частности алгебраические типы и параметрический полиморфизм, которые обеспечивают удобную и безопасную работу функций с коллекциями (списками) независимо от типа значений. Новые языки для JS также зачастую заимствуют из них, так что знакомство с ML полезно для их понимания.
Традиционное применение OCaml и языков семейства ML — разработка компиляторов, средств статического анализа и автоматического доказательства теорем. К примеру, на нем был написан компилятор Rust до того, как он научился компилировать сам себя. OCaml также нашел применение в финансовой сфере, где ошибка в коде может за пару минут довести компанию до банкротства, например в Lexifi и Jane Street.
Пригодным к применению в качестве скриптового его делает особенность реализации: он предоставляет одновременно интерпретатор, компилятор в байт-код и компилятор в машинный код для популярных платформ, в том числе x86 и ARM. Можно начать разработку в интерактивной оболочке интерпретатора, затем записать код в файл. А если скрипт превращается в полноценную программу, скомпилировать ее в машинный код.
В отличие от Haskell, в OCaml используется строгая, а не ленивая модель вычислений, что упрощает ввод-вывод и анализ производительности. Кроме того, он поддерживает изменяемые переменные (ссылки) и прочие средства императивного программирования.
Мы не будем затрагивать веб-скрипты и сосредоточимся на традиционных. В этой статье я также намеренно опускаю создание собственных типов, систему модулей и многие другие возможности. Первая цель — показать «вкус» языка.
Стандартным менеджером пакетов для OCaml стал OPAM. Он может устанавливать сам компилятор, библиотеки и переключаться между разными версиями. Многие системы предоставляют какую-то версию OCaml в репозиториях (часто устаревшую), но с помощью OPAM легко поставить самую свежую от имени обычного пользователя. Для Linux и macOS авторы предоставляют статически скомпилированную версию.
После установки мы поставим самую новую на настоящий момент версию компилятора 4.07 и несколько утилит и библиотек, которые потребуются нам в примерах.
$ opam switch 4.05
$ opam install utop lambdasoup
Для проверки работоспособности запустим utop
— интерактивную оболочку интерпретатора. Стандартный интерпретатор (ocaml
) слишком «спартанский» — без поддержки истории команд и автодополнения, поэтому его мы будем использовать только в неинтерактивном режиме.
$ utop
utop # print_endline "hello world" ;;
hello world
- : unit = ()
Интерактивный интерпретатор позволяет вводить многострочные выражения, но из-за этого для завершения ввода нужно применять символ ;;
. Использовать его в исходном коде допустимо, но излишне.
Источник: xakep.ru