Почему проще писать компилятор на функциональном языке?

Я очень долго думал об этом вопросе, но на самом деле не смог найти ответ на Google, а также аналогичный вопрос в Stackoverflow. Если есть дубликат, я сожалею об этом.

Многие люди, похоже, говорят, что писать компиляторы и другие языковые инструменты на функциональных языках, таких как OCaml и Haskell, намного эффективнее и проще, чем писать на императивных языках.

Это правда? И если да - почему так эффективно и легко писать их в функциональных языках, а не на императивном языке, например C? Кроме того - не является языковым инструментом на функциональном языке медленнее, чем на каком-то низкоуровневом языке, таком как C?

Ответ 1

Часто компилятор много работает с деревьями. Исходный код анализируется в дереве синтаксиса. Затем это дерево может быть преобразовано в другое дерево с аннотациями типа для проверки типов. Теперь вы можете преобразовать это дерево в дерево, содержащее только элементы основного языка (преобразование синтаксических обозначений, подобных сахару, в незатвержденную форму). Теперь вы можете выполнять различные оптимизации, которые в основном являются преобразованиями на дереве. После этого вы, вероятно, создадите дерево в некоторой нормальной форме, а затем перейдете по этому дереву, чтобы создать целевой (сборный) код.

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

Ответ 2

Множество задач компилятора - это сопоставление шаблонов по древовидным структурам.

Оба OCaml и Haskell имеют мощные и сжатые возможности сопоставления шаблонов.

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

Ответ 3

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

В моей последней работе с компилятором-esque мы использовали OCaml именно по этой причине, манипулируя кодом C, это был лучший инструмент для этой задачи. Если бы люди в INRIA построили OCaml с разными приоритетами, возможно, это было не так хорошо.

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

/me: отскакивает назад к моим задачам Java немного менее радостно...

Ответ 4

См. также

шаблон дизайна F #

FP группирует вещи "по операции", тогда как группы OO "по типу" и "по операции" более естественны для компилятора/интерпретатора.

Ответ 5

В принципе, компилятор представляет собой преобразование из одного набора кода в другое - от источника к IR, от IR до оптимизированного IR, от IR до сборки и т.д. Это именно то, что функциональные языки предназначены для: чистая функция - это просто переход от одной вещи к другой. Императивные функции не имеют такого качества. Хотя вы можете написать такой код на императивном языке, для него специализируются функциональные языки.

Ответ 6

Одна из возможностей заключается в том, что компилятор имеет тенденцию иметь дело очень осторожно со всем множеством угловых случаев. Получение правильного кода часто упрощается с помощью шаблонов проектирования, которые структурируют реализацию таким образом, который соответствует правилам, которые он реализует. Часто это становится декларативным (шаблонное совпадение, "where" ), а не императивным (упорядочивание, "когда" ) дизайн и, следовательно, проще реализовать на декларативном языке (и большинство из них функциональны).

Ответ 7

Кажется, все пропустили еще одну важную причину. Очень легко написать встроенный доменный язык (EDSL) для парсеров, которые очень похожи (B) BNF в нормальном коде. Компараторы Parser, такие как Parsec, довольно легко писать на функциональных языках, используя функции более высокого порядка и состав функций. Не только проще, но и очень элегантно.

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

Это не единственный способ сделать исходные рамки курса.