Дефункционализация: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[отпатрулированная версия][отпатрулированная версия]
Содержимое удалено Содержимое добавлено
мНет описания правки
done
Строка 1: Строка 1:
{{редактирую|1=[[Служебная:Contributions/George Shuklin|George Shuklin]]|2=13 августа 2019 |3= 08:42 (UTC)|details=}}
{{переведённая статья|en|Defunctionalization|версия=882420854}}
{{переведённая статья|en|Defunctionalization|версия=882420854}}
'''Дефункционализация''' - в [[язык программирования|программировании]] означает преобразование программы на этапе компиляции заменяющее [[функция высшего порядка|функции высшего порядка]] на вызов одной-единственной функции применения (apply). Эта техника впервые была описана Джоном С. Рейнольдом ({{en|John C. Reynolds}}) в его работе 1972 года, "Определяющие интерпретаторы для языков высшего порядка" ({{en|Definitional Interpreters for Higher-Order Programming Languages}}). Рейнольд отметил, что так как любая конкретная программа содержит конечное количество функциональных абстракций, то любая из этих абстракций может быть заменена уникальным идентификатором. Каждое применение функции в такой программе заменяется вызовом функции apply с идентификатором функции в качестве первого параметра, которая и выполняет связанные с заданным идентфикатором операции над оставшимися аргументами.
'''Дефункционализация''' - в [[язык программирования|программировании]] означает преобразование программы на этапе компиляции заменяющее [[функция высшего порядка|функции высшего порядка]] на вызов одной-единственной функции применения (apply). Эта техника впервые была описана Джоном С. Рейнольдом ({{en|John C. Reynolds}}) в его работе 1972 года, "Определяющие интерпретаторы для языков высшего порядка" ({{en|Definitional Interpreters for Higher-Order Programming Languages}}). Рейнольд отметил, что так как любая конкретная программа содержит конечное количество функциональных абстракций, то любая из этих абстракций может быть заменена уникальным идентификатором. Каждое применение функции в такой программе заменяется вызовом функции apply с идентификатором функции в качестве первого параметра, которая и выполняет связанные с заданным идентификатором операции над оставшимися аргументами.


Одним из затруднений для этой идеи состоит в том, что фунциональная абстракция может ссылаться на [[свободная переменная|свободные переменные]]. В такой ситуации до выполнения ''дефункционализации'' должен быть выполнен [[лямда-лифтинг]] (конвертация свободных перменных в [[Замыкание_(программирование)|замыкание]]), Таким образом, чтобы любая свободная перменная функциональной абстракции передавалась в качестве аргумента в функцию apply. Кроме того, если замывание поддерживается в качестве [[объект первого класса|значения первого класса]], то необходимо обеспечить создание новых структур данных для представления захваченных значений.
Одним из затруднений для этой идеи состоит в том, что функциональная абстракция может ссылаться на [[свободная переменная|свободные переменные]]. В такой ситуации до выполнения ''дефункционализации'' должен быть выполнен [[лямда-лифтинг]] (конвертация свободных переменных в [[Замыкание_(программирование)|замыкание]]), Таким образом, чтобы любая свободная переменная функциональной абстракции передавалась в качестве аргумента в функцию apply. Кроме того, если замывание поддерживается в качестве [[объект первого класса|значения первого класса]], то необходимо обеспечить создание новых структур данных для представления захваченных значений.


Вместо использования единственной функции apply для обработки всех случаев, могут использоваться различные методы [[Анализ_потока_управления|анализа потока управления]] (включая простейшее различение разных видов [[Арность|арности]] (числа аргументов) или [[сигнатура типа|сигнатур типов]]) для разделения apply на несколько специализированных функций. Альтернативно, язык программирования может поддерживать [[указатель на функцию|указатели на функции]], использование которых может быть более эффективным, чем подход с диспетчеризацией.
Вместо использования единственной функции apply для обработки всех случаев, могут использоваться различные методы [[Анализ_потока_управления|анализа потока управления]] (включая простейшее различение разных видов [[Арность|арности]] (числа аргументов) или [[сигнатура типа|сигнатур типов]]) для разделения apply на несколько специализированных функций. Альтернативно, язык программирования может поддерживать [[указатель на функцию|указатели на функции]], использование которых может быть более эффективным, чем подход с диспетчеризацией.


Помимо использования для компиляции функциональных языков высшего порядка, дефункционализация так же исследовалась как метод механистического преобразования [[интерпретатор]]а в [[абстрактная машина|абстрактную машину]]. Дефункционализация так же связана с техникой представления функций с помощью [[функциональный объект|функциональных объектов]] в [[объектно-ориентированное программирование|объектно-ориентированного программирования]] (как альтернатива использованию замыканий).
<!--

Besides its use as a compilation technique for higher-order [[functional languages]], defunctionalization has been studied (particularly by [[Olivier Danvy]] and collaborators) as a way of mechanically transforming [[Interpreter (computing)|interpreters]] into [[abstract machine]]s. Defunctionalization is also related to the technique from [[object-oriented programming]] of representing functions by [[function object]]s (as an alternative to closures).
-->


== Пример ==
== Пример ==

Версия от 09:04, 13 августа 2019

Дефункционализация - в программировании означает преобразование программы на этапе компиляции заменяющее функции высшего порядка на вызов одной-единственной функции применения (apply). Эта техника впервые была описана Джоном С. Рейнольдом (John C. Reynolds) в его работе 1972 года, "Определяющие интерпретаторы для языков высшего порядка" (Definitional Interpreters for Higher-Order Programming Languages). Рейнольд отметил, что так как любая конкретная программа содержит конечное количество функциональных абстракций, то любая из этих абстракций может быть заменена уникальным идентификатором. Каждое применение функции в такой программе заменяется вызовом функции apply с идентификатором функции в качестве первого параметра, которая и выполняет связанные с заданным идентификатором операции над оставшимися аргументами.

Одним из затруднений для этой идеи состоит в том, что функциональная абстракция может ссылаться на свободные переменные. В такой ситуации до выполнения дефункционализации должен быть выполнен лямда-лифтинг (конвертация свободных переменных в замыкание), Таким образом, чтобы любая свободная переменная функциональной абстракции передавалась в качестве аргумента в функцию apply. Кроме того, если замывание поддерживается в качестве значения первого класса, то необходимо обеспечить создание новых структур данных для представления захваченных значений.

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

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

Пример

Этот пример предоставлен Оливером Данви (Olivier Danvy), переведённым на Хаскель.

Для типа данных Tree:

data Tree a = Leaf a
            | Node (Tree a) (Tree a)

Производим дефункционализацию следующей программы:

cons :: a -> [a] -> [a]
cons x xs = x : xs

o :: (b -> c) -> (a -> b) -> a -> c
o f g x = f (g x)

flatten :: Tree t -> [t]
flatten t = walk t []

walk :: Tree t -> [t] -> [t]
walk (Leaf x)     = cons x
walk (Node t1 t2) = o (walk t1) (walk t2)

Мы производим дефункционализацию посредством замены всех функций высшего порядка (cons, o, and walk)значением типа Lam, и вместо прямого вызова функций, мы используем функцию apply, обрабатывающую этот значения этого типа:


data Lam a = LamCons a
           | LamO (Lam a) (Lam a)

apply :: Lam a -> [a] -> [a]
apply (LamCons x)  xs = x : xs
apply (LamO f1 f2) xs = apply f1 (apply f2 xs)

cons_def :: a -> Lam a
cons_def x  = LamCons x

o_def :: Lam a -> Lam a -> Lam a
o_def f1 f2 = LamO f1 f2

flatten_def :: Tree t -> [t]
flatten_def t = apply (walk_def t) []

walk_def :: Tree t -> Lam t
walk_def (Leaf x)     = cons_def x
walk_def (Node t1 t2) = o_def (walk_def t1) (walk_def t2)

Примечания

Ссылки

  • Reynolds, John (August 1972). "Definitional Interpreters for Higher-Order Programming Languages" (PDF). Proceedings of the ACM Annual Conference. Boston, Massachusetts. pp. 717—740. doi:10.1145/800194.805852. {{cite conference}}: Неизвестный параметр |booktitle= игнорируется (|book-title= предлагается) (справка)
  • Danvy, Olivier; Nielsen, Lasse R. (2001). "Defunctionalization at Work" (PDF). Proceedings of the ACM SIGPLAN Conference on Principles and Practice of Declarative Programming. pp. 162—174. doi:10.1145/773184.773202. {{cite conference}}: Неизвестный параметр |booktitle= игнорируется (|book-title= предлагается) (справка) (More comprehensive version: Technical Report BRICS-RS-01-23)
  • Danvy, Olivier; Millikin, Kevin R. (June 2009). "Refunctionalization at Work". Science of Computer Programming. 74 (8): 534—549. doi:10.1016/j.scico.2007.10.007. (Also available as Technical Report BRICS-RS-07-7)

Внешние ссылки