Чем функциональный язык отличается от языковой реализации - PullRequest
13 голосов
/ 07 декабря 2009

Существует совершенно новая парадигма «функционального программирования», которая требует полного изменения шаблонов мышления по сравнению с процедурным программированием. Он использует функции высшего порядка, чистоту, монады и т. Д., Которые мы обычно не видим в императивных и объектно-ориентированных языках.

Мой вопрос заключается в том, как реализация этих языков отличается от императивных или объектно-ориентированных языков, например, в отношении управления памятью или внутренних объектов, таких как указатели и т. Д.

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

Ответы [ 7 ]

8 голосов
/ 07 декабря 2009

Код, полученный из функциональных языков, использует множество функций, которые вы видите в различной степени в нефункциональных языках. Сборка мусора перешла в общее использование. Оптимизация хвостового вызова выполняется в GCC и VC ++ .

Однако замыкания являются отличительной чертой функционального программирования. Вы не видите одно без другого. Если вы определяете «функциональные языки» для ссылки только на чисто функциональные языки, они не являются синонимами, поскольку вы обнаружите замыкания в императивных языках, которые поддерживают функциональное программирование (например, Javascript и Scheme (что является технически обязательным, хотя функциональная парадигма - это то, что в основном используемый)). Замыкания могут быть реализованы с помощью стека спагетти для стека вызовов, либо путем копирования локальных переменных при выходе из стекового фрейма, либо путем выделения локальных переменных в куче и предоставления возможности для сбора мусора позаботиться о них.

Когда у вас есть замыкания, анонимные функции относительно просты (с переводчиком они действительно просты). При использовании компилятора функция преобразуется в байт-код во время компиляции, а байт-код (точнее, адрес точки входа) ассоциируется во время выполнения с текущей средой.

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

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

5 голосов
/ 07 декабря 2009

Реализации языков функционального программирования используют широкий спектр методов реализации. Прекрасное введение в реализацию Scheme (диалект Lisp) дает эту книгу: Lisp in Small Pieces от Christian Queinnec.

1 голос
/ 09 декабря 2009

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

Компилятор для такого языка должен сделать несколько вставок и несколько оптимизаций замыкания для создания достойного кода. (Для меня эти базовые оптимизации замыкания кажутся нетривиальными - анализ побега и т. Д. - но это может быть просто отсутствие знакомства.)

1 голос
/ 07 декабря 2009

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

1 голос
/ 07 декабря 2009

Я полагаю, что есть много аспектов, которые заслуживают особого внимания в функциональных языках, один из которых приходит на ум:

Функциональные языки часто используют рекурсию. Поэтому любая реализация должна пытаться оптимизировать этот случай. Например. идентифицируйте хвостовую рекурсию и внутренне преобразуйте в цикл (таким образом сохраняя издержки вызова функции, такие как сохранение / восстановление стека). (http://en.wikipedia.org/wiki/Tail_recursion)

0 голосов
/ 24 февраля 2011

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

Тем не менее, есть аргументы эффективности, которые предпочитают замыкания по сравнению с глобальными (особенно в контексте реализации компилятора). [Но я знаю о функциональных языках, которые не обеспечивают замыкания напрямую, хотя могут быть реализованы «рабочие перемены».]

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

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

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

0 голосов
/ 07 декабря 2009

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

...