Я полный новичок с OCaml. Недавно я наткнулся на эту страницу со списком критических замечаний по отношению к OCaml.
Видя, что эта страница довольно старая (2007 год): какие из перечисленных здесь пунктов пули все еще актуальны сегодня? Например: все еще верно, что невозможно напечатать универсальный объект?
Я хочу прояснить, что я не хочу обсуждать высказанные в нем мнения. Я спрашиваю, является ли приведенная информация, такая как факт переполнения целых чисел без предупреждений, все еще правильной для более поздних версий OCaml
Ответы:
Эта статья обсуждается в нескольких местах:
Подводя итог: да, OCaml не Лисп, и нет, он не идеален (что это значит?). Я не думаю, что пункты, упомянутые в сообщении в блоге, актуальны для повседневных программистов O'Caml.
Изучив O'Caml, я думаю, что это интересный язык, который может помочь вам создавать программы, на которые вы даже не посмели бы писать, скажем, на C / C ++ / Java: например, взглянуть на Frama-C .
Чтобы получить более свежее описание O'Caml, я рекомендую вам прочитать о его возможностях : язык поддерживает строгие статические методы проверки типов, которые позволяют реализациям сосредоточиться на создании производительных, но безопасных сред выполнения.
Важно : я не эксперт OCaml: если вы один из них и видите, что я написал что-то ужасно неправильно, пожалуйста, исправьте меня. Я буду редактировать этот пост соответственно.
Проверка статического типа
Ложное чувство безопасности
Это правда, но очевидно.
Статическая типизация дает вам доказательства того, что вы можете доверять подмножеству свойств вашей программы. Если вы не согласитесь пройти все формально, обычная (не игрушка) программа будет подвержена ошибкам программирования, которые могут быть обнаружены только во время выполнения.
Именно тогда могут применяться методы динамической проверки: у компилятора OCaml есть флаги для генерации исполняемых файлов с отладочной информацией и т. Д. Или он может генерировать код, который слепо доверяет программисту и максимально стирает информацию о типах. Программисты, которым нужны надежные программы, должны явно выполнять динамические проверки.
То же самое относится, например, к Common Lisp, но наоборот: сначала динамические типы, а затем необязательные объявления типов и директивы компилятора.
Несколько основных типов
Все еще применяется: основной язык не изменился (или не сильно).
Silent Integer Overflow
Это норма в большинстве языков, когда целочисленное переполнение проверяется руками. Я не знаю ни одной библиотеки, которая выполняла бы операции проверки типов для проверки возможности переполнения.
Модуль неизменяемости
Автор упоминает Функторы, но я не вижу, как его пример не может быть реализован. Читая главу « Модули первого класса» на https://realworldocaml.org , кажется, что модули могут использоваться для создания и создания новых модулей. Конечно, изменение существующего модуля требует модификации исходного кода, но, опять же, это не является необычным среди языков программирования.
« Семантически функции скомпилированы INLINE»
Поток reddit выше не согласен, говоря, что привязка разрешается во время ссылки. Тем не менее, это деталь реализации, и я думаю, что семантически выделенное относится к способу разрешения функций. Пример:
Вышеприведенная программа компилируется и при выполнении возвращает 5, поскольку
g
определяется с первой версиейf
, как если бы вызывающая функцияg
встроила вызовf
. Между прочим, это не «плохо», это просто соответствует правилам теневого копирования имен О'Камла.Подводя итог : да, модули являются неизменяемыми . Но они также являются составными .
Полиморфизм вызывает ошибки типа времени выполнения
Я не могу воспроизвести упомянутую ошибку. Я подозреваю, что это ошибка компилятора.
Нет макросов
Действительно, нет макросов, но есть препроцессоры (OcamlP4, OcamlP5, ...).
Упаковщики (с открытым файлом)
Зная, как UNWIND-PROTECT может быть полезен, действительно больно видеть, что его нет в других языках. Вот несколько вариантов:
места
Я не думаю, что обобщенные ссылки существуют в OCaml.
Незначительная языковая Suckiness
Запись поля именования ада
Правда, но вы должны использовать модули:
Синтаксис
Все еще применяется (но на самом деле, это всего лишь синтаксис).
Нет полиморфизма
Все еще применяется, но почему-то есть люди, которые предпочитают это вместо числовой башни Лиспа (я не знаю почему). Я полагаю, это помогает с выводом типа.
Несовместимые наборы функций
См. Проект « Аккумуляторы OCaml включены ». В частности, BatArray , для примера
map2
для массивов.Нет динамических переменных
Может быть реализовано:
Необязательные аргументы ~ отстой
По языковым ограничениям в Common Lisp нельзя смешивать необязательные аргументы и аргументы с ключевыми словами. Значит ли это, что это отстой? (конечно, это можно изменить с помощью макросов (см., например, мой ответ )). См. Документацию O'Caml для дополнительных и именованных аргументов в O'Caml.
Частичное несоответствие приложения аргументу
Я не думаю, что это действительно раздражает на практике.
Читаемость арифметики
Это верно, но вы можете использовать R или Python для численных задач, если хотите.
Бесшумное разрешение конфликтов имен
Все еще применяется, но обратите внимание, что это хорошо задокументировано.
Нет ввода / вывода объекта
Все еще применяется.
Реализация, библиотеки
Они постоянно меняются каждый день: однозначного ответа нет.
В заключение,
... все еще применяется.
источник
Ложное чувство безопасности . Это нонсенс.
Несколько основных типов . В OCaml теперь есть байты и байтовые массивы, но нет встроенных юникодных строк, 16-битных целых, беззнаковых целых, 32-битных чисел с плавающей точкой, векторов или матриц. Сторонние библиотеки предоставляют некоторые из них.
Silent Integer Overflow . Без изменений, но это никогда не было проблемой.
Неизменность модуля . Его рекомендация, что функции и модули должны быть изменяемыми, является мрачным возвратом к Lisp и действительно плохой идеей. Вы можете заменить модули, используя,
include
если хотите, но, конечно, не можете изменять их.Полиморфизм вызывает ошибки типа времени выполнения . Это большая проблема с OCaml, и она не была исправлена. Поскольку ваши типы развивают полиморфное равенство, сравнение и хеширование начинают терпеть неудачу, когда они сталкиваются с такими типами, как функции, и отладка проблемы становится очень сложной. У F # есть отличное решение этой проблемы.
Нет макросов . По иронии судьбы, когда он писал этот OCaml, он полностью поддерживал макросы, но теперь они решили использовать эту функцию.
Упаковщики . Это была настоящая проблема, и она не была исправлена. В
try ... finally
языке OCaml до сих пор нет конструкции и нет оболочки, реализующей ее в stdlib.Места . Без изменений, но не проблема.
Запись поля именования ада . Структурируйте свой код правильно, используя модули.
Синтаксис . Без изменений, но не проблема.
Полиморфизма нет . В основном это была ерунда, когда он это написал, и ничего не изменилось.
Несовместимые наборы функций . OCaml до сих пор не имеет
cons
функции. Все в порядке. Я не хочу, чтобы Лисп на моем языке, спасибо.Нет динамических переменных . Была хорошая вещь об OCaml. Все еще хорошая вещь об OCaml.
Необязательные аргументы ~ отстой . Необязательные аргументы рок. Я подписал Microsoft, чтобы они добавили необязательные аргументы в F #.
Частичное несоответствие приложения аргументу . А?
Читаемость арифметики . Это изменилось с тех пор, как я перестал использовать OCaml ~ 8 лет назад. Видимо, теперь вы можете сделать
Int64.((q * n - s * s) / (n - 1L))
.Бесшумное разрешение конфликтов имен . Он пытался сделать полноценную разработку программного обеспечения в REPL, как вы это делали в Lisp. Не делай этого в OCaml. Используйте файлы и пакетную компиляцию, прибегая к REPL, только для тестирования, запуска одноразового кода и интерактивных технических вычислений.
Порядок оценки . Это было неправильно, когда он написал это. Порядок оценки не определен в OCaml.
Нет ввода / вывода объекта . Он привел стороннюю библиотеку, которая уже решила эту «проблему».
Компилятор останавливается после первой ошибки . А?
Нет трассировки стека для изначально скомпилированных исполняемых файлов . Исправлена.
Отладчик отстой . Я никогда не использовал отладчик. Статическая проверка типов ловит почти все мои ошибки.
GC отстой . Я нашел GC OCaml превосходным, за исключением одной главной проблемы: глобальная блокировка предотвращает параллельное программирование.
Нет неявных предварительных объявлений . Взаимная рекурсия явно предусмотрена во всех ML. Единственным недостатком является то, что
type
определения являются рекурсивными по умолчанию, тогда какlet
привязки не являются рекурсивными по умолчанию.Функция обхода отсутствует . В OCaml все еще есть простой stdlib, но сторонние библиотеки, такие как Jane St's Core
round
и друзья.Списки .
List.map
все еще не хвостовой рекурсив Я представил патчи, чтобы исправить серьезные ошибки, подобные этой, и мне пришлось ждать годы, прежде чем они появятся в релизах. Списки все еще неизменны, конечно. И так должно быть.Скорость . Я считаю, что время компиляции для больших полиморфных вариантов было исправлено.
Сопоставление с образцом . Торжество надежды над реальностью. Сообществу Lisp не удалось этого сделать. Отсюда мое 10-е правило: любая достаточно сложная программа на Лиспе содержит специальную, неофициально заданную и ошибочную реализацию половины компилятора сопоставления с образцами OCaml.
Когда он написал, что вы не могли просто сделать:
но вы можете вызвать симпатичный принтер с верхнего уровня как библиотечный вызов, предоставив ему необходимую информацию о типе. И был макрос, который вы можете использовать для аннотирования структур данных, чтобы автоматически создавать красивые принтеры.
источник
cons
дает плохой тон (оригинальная статья напыщенная, но вам не нужно ее копировать).+
ints, float и complex, но вы также можете определить свои собственные типы и добавить перегрузку для+
работы с вашим типом. Это обеспечивает краткость и удобочитаемость Lisp или Haskell с предсказуемо хорошей производительностью SML или OCaml, достигая того, чего не делает ни один другой язык.