Функційне програмування: відмінності між версіями

[перевірена версія][перевірена версія]
Вилучено вміст Додано вміст
м →‎Чисті функції: вікіфікація
Немає опису редагування
Рядок 8:
Основну увагу функційним мовам програмування, особливо, «чисто функційним», приділили академічні дослідники. Однак, до відомих функційних мов програмування, які використовуються в промисловості та комерційному програмуванні належить [[Erlang]] (паралельні програми), [[R (мова програмування)|R]] (статистика), [[Mathematica]] (символьні обчислення)), [[J (мова програмування)|J]] та [[K (мова програмування)|K]] ([[фінансовий аналіз]]), та спеціалізовані мови програмування наприклад [[XSLT]]. Істотний вплив на функційне програмування здійснило [[лямбда-числення]], мова програмування [[APL (мова програмування)|APL]], мова програмування [[Lisp]] та новіша мова програмування [[Haskell]].
 
Функційне програмування часто називають «функціональним», хоча насправді [[функціонально-орієнтоване програмування]]  — це інша категорія, де основою є компонування програм у ряд програмних продуктів.
 
== Мови програмування ==
Найвідомішими мовами функційного програмування є:
* [[XQuery]]
* [[Haskell]]  — чистий функційний. Названий на честь [[Хаскелл Каррі|Хаскелла Каррі]]
* [[LISP]] (Джон Маккарті, 1958, безліч його нащадків, найсучасніші з яких  — [[Scheme]] і [[Common Lisp]])
* [[ML]] (Робін Мілнер, 1979, з нині використовуваних діалектів відомі [[Standard ML]] і [[Objective CAML]])
* [[Miranda]] (Девід Тернер, 1985, який згодом дав розвиток мові [[Haskell]])
* [[Erlang]]  — (Joe Armstrong, 1986) функційна мова з підтримкою процесів
* [[Nemerle]]  — гібридна функціонально/імперативна мова.
* [[F sharp (мова програмування)|F#]] - — функційна мова для платформи [[.NET]]
* [[Scala]]  — гібридна об'єктно-орієнтована/функційна мова для платформи [[Java]]
* [[Clojure]]  — функційна мова для платформи [[Java]]
 
Ще не повністю функційні початкові версії і [[Lisp]] і [[APL]] внесли особливий внесок до створення і розвитку функційного програмування. Пізніші версії Lisp, такі як [[Scheme]], а так само різні варіанти [[APL]] підтримували властивості і концепції функційної мови.
Рядок 28:
 
== Історія ==
[[Лямбда-числення]] стало теоретичною базою для опису і обчислення функцій. Будучи математичною [[Абстракція|абстракцією]], а не [[Мова програмування|мовою програмування]], воно склало базис майже всіх мов функціонального програмування на сьогоднішній день. Подібне теоретичне поняття, [[комбінаторна логіка]], є більш абстрактним, ніж λ-числення і було створено раніше. Ця логіка використовується в деяких езотеричних мовах, наприклад в [[Unlambda]]. І λ-числення, і комбінаторна логіка були розроблені для більш ясного й точного опису принципів і основ математики <ref> {{книга|автор = [[Пенроуз, Роджер|Роджер Пенроуз]]|частина = Глава 2: Лямбда-числення Черча|заголовок = Новий розум короля. Про комп'ютери, мисленні і законах фізики|оригінал = The Emperors New Mind: Concerning Computers, Minds and The Laws of Physics | видавництво = Едіторіал УРСС|рік = 2003 | isbn = 5-354-00005-X}} + перевидання ISBN 978 -&nbsp;— 5-382-01266-7; 2011 </ref>.
 
Першим функціональною мовою був [[Lisp]], створений [[Джон МакКарті | Джоном МакКарті]] в період його роботи в [[Массачусетський технологічний інститут | Массачусетському технологічному інституті]] в кінці п'ятдесятих і реалізований, спочатку, для {{нп3|IBM 700/7000 | | | IBM 700/7000 series}} <ref> {{cite journal | first = John | last = McCarthy | authorlink = John McCarthy (computer scientist) | title = History of Lisp | journal = In [[Association for Computing Machinery|ACM]] SIGPLAN History of Programming Languages ​​Conference | pages = 217-223 | month = June | year = 1978 | url = http://citeseer.ist.psu.edu/mccarthy78history.html|doi=10.1145/ 800025.808387}} </ref>. Lisp ввів безліч понять функціональної мови, хоча при цьому сповідував не тільки парадигму функціонального програмування {{sfn | J. Harrison | 1997 | loc = Гл. 3. λ-числення як мова програмування}}. Подальшим розвитком Ліспу стали такі мови як [[Scheme]] і [[Dylan (мова програмування)|Dylan]].
 
Мова обробки інформації ({{нп3 | Information Processing Language}}, IPL) іноді визначається як найперший машинно-функціональна мова <ref> У своїх мемуарах [[Герберт Саймон]] (1991),'' Models of My Life'' pp. 189-190189–190 ISBN 0-465-04640-1 стверджує, що його, Al. Ньюелл, і Кліфф Шоу яких «часто називають батьками штучного інтелекту» за написання програми {{нп3 | Logic Theorist}} автоматично доводить теореми з'' {{нп3 | Principia Mathematica}}''. Для того, щоб досягти цього, вони повинні були придумати мову і парадигму, яку, ретроспективно, можна розглядати як функціональне програмування. </Ref>. Це мова [[Мова асемблера | ассемблерного]] типу для роботи зі списком символів. У ньому було поняття «генератора», який використовував функцію як аргумент, а також, оскільки це мова ассемблерного рівня, він може позиціонуватися як мова, що має функції вищого порядку. Однак, в цілому IPL акцентовано на використання імперативних понять <ref> [http://hopl.murdoch.edu.au/showlanguage.prx?exp=13&language=IPL History of Programming Languages: IPL] </ref>.
 
[[Айверсон, Кеннет Юджин | Кеннет Е. Айверсон]] розробив мову [[АПЛ (мова програмування) | APL]] на початку шістдесятих, документувати його в своїй книзі A Programming Language (ISBN 9780471430148) <ref> {{книга | частина = XIV. APL Session | заголовок = History of Programming Language | ISBN = 0-12-745040-8 | відповідальний = Richard L. Wexelbblat | видавництво = Academic Press | рік = 1981 | сторінки = 661-693 | сторінок = 749}} </ref>. APL справив значний вплив на мову {{нп3 | FP | | | FP (programming language)}}, створений [[Бекуса, Джон | Джоном Бекуса]]. На початку дев'яностих Айверсон і {{нп3 | Роджер Хуей | | | Roger Hui}} створили наступника APL -&nbsp;— мова програмування [[J (мова програмування) | J]]. У середині дев'яностих {{нп3 | Артур Вітні | | | Arthur Whitney}}, який раніше працював з Айверсон, створив мову [[K (мова програмування) | K]], який згодом використовувався у фінансовій індустрії на комерційній основі.
 
У сімдесятих в [[Единбурзький університет | університеті Единбурга]] [[Робін Мілнер]] створив мову [[ML]], а [[Тернер, Девід | Девід Тернер]] починав розробку мови [[SASL(мова програмування)|SASL]] в [[Сент-Ендрюського університету | університеті Сент-Ендрюса]] і, згодом, мову [[Міранда (мова програмування) | Miranda]] в університеті міста Кент. У кінцевому підсумку на основі ML були створені кілька мов, серед яких найбільш відомі [[OCaml | Objective Caml]] і [[SML | Standard ML]]. Також в сімдесятих здійснювалася розробка мови програмування, побудованого за принципом Scheme (реалізація не лише функціональної парадигми), що отримав опис у відомій роботі «Lambda Papers», а також у книзі вісімдесят п'ятого року «"[[Структура та інтерпретація комп'ютерних програм | Structure and Interpretation of Computer Programs]] »", в якій принципи функціонального програмування були донесені до більш широкої аудиторії. {{Ні АІ | 18 | 05 | 2009fact}}
 
У вісімдесятих [[Мартін-Леф, Пер | Пер Мартін-Леф]] створив интуиционистскойінтуціонистську теорію типів (також звану конструктивноїконструктивною). У цій теорії функціональне програмування отримало конструктивне доказ того, що раніше було відомо як залежний тип. Це дало потужний поштовх до розвитку діалогового докази теорем і до подальшого створення безлічі функціональних мов.
 
[[Haskell]] був створений в кінці вісімдесятих у спробі поєднати безліч ідей, отриманих у ході дослідження функціонального програмування. {{-1 | <ref Name="hudak1989"> {{cite journal | author = {{нп3 | Хьюдак, Пол | Пол Хьюдак | en | Paul Hudak}} | title = Conception, evolution, and application of functional programming languages ​​| journal = [[Association for Computing Machinery | ACM]] Computing Surveys | volume = 21 | issue = 3 | pages = 359 -411−411 | month = September | year = 1989 | url = }} </Refref>}}
 
== Концепції ==
Деякі концепції та парадигми специфічні для функціонального програмування і в основному чужі імперативному програмуванню (включаючи [[об'єктно-орієнтоване програмування]]). Тим не менш, мови програмування звичайно являють собою гібрид декількох парадигм програмування, тому «здебільшого імперативні» мови програмування можуть використовувати які-небудь з цих концепцій. {{Ні АІ | 18 | 05 | 2009fact}}
 
=== Функції вищих порядків ===
{{Main | Функція вищого порядку}}
Функції вищих порядків -&nbsp;— це такі функції, які можуть приймати в якості аргументів і повертати інші функції. <ref Name="functional"> [http://wm-help.net/books/book/49.html Завантажити PDF: «"Техніки функціонального програмування, В. &nbsp;А. &nbsp;Потапенко »«стор. 8«» Функції вищих порядків »"]. </ref> Математики таку функцію частіше називають [[оператор (математика) | оператором]], наприклад, оператор взяття похідної або інтегральний оператор.
 
Функції вищих порядків дозволяють використовувати [[Каррірованіе | каррінг]] -&nbsp;— перетворення функції від пари аргументів у функцію, що бере свої аргументи по одному. Це перетворення отримало свою назву на честь [[Каррі, Хаскелл | Х. Каррі]].
 
=== Чисті функції ===
Рядок 62 ⟶ 63:
=== Рекурсія ===
{{Main | Рекурсія}}
У функціональних мовах [[Цикл (програмування)|цикл]] зазвичай реалізується у вигляді рекурсії. Строго кажучи, в функціональної парадигми програмування немає такого поняття, як цикл. Рекурсивні функції викликають самі себе, дозволяючи операції виконуватися знову і знову. Для використання рекурсії може знадобитися великий [[стек]], але цього можна уникнути в разі [[Хвостова рекурсія | хвостовій рекурсії]]. Хвостова рекурсія може бути розпізнана і оптимізована компілятором в код, одержуваний після компіляції аналогічної ітерації в імперативному мові програмування. <ref> [Http://c2.com/cgi/wiki?TailCallOptimization Tail call optimization] </ref> Стандарти мови Scheme вимагають розпізнавати і оптимізувати хвостову рекурсію. Оптимізувати хвостову рекурсію можна шляхом перетворення програми в стилі використання продовжень при її компіляції, як один із способів. <ref> [Http://www.schemers.org/Documents/Standards/R5RS/ Revised5 Report on the Algorithmic Language Scheme, 3.5. Proper tail recursion] </ref>
 
Рекурсивні функції можна узагальнити за допомогою функцій вищих порядків, використовуючи, наприклад, [[катаморфізм]] і [[анаморфізм]] (або «згортка» і «розгорнення»). Функції такого роду відіграють роль такого поняття як цикл в імперативних мовах програмування. {{Ні АІ | 18 | 05 | 2009fact}}
 
=== Підхід до обчислення аргументів ===
Рядок 72 ⟶ 73:
print (len ([2 +1, 3 * 2, 1/0, 5-4]))
</Source>
на виході буде помилка, так як в третьому елементі списку присутній поділ на нуль. При нестрогому підході значенням виразу буде 4, оскільки для обчислення довжини списку значення його елементів, строго кажучи, не важливі і можуть взагалі не обчислюватися. При строгому (апплікатівном) порядок обчислення заздалегідь підраховуються значення всіх аргументів перед обчисленням самої функції. При нестрогому підході (нормальний порядок обчислення) значення аргументів не обчислюються до тих пір, поки їх значення не знадобиться при обчисленні функції <ref name="lenivie">'' Н. &nbsp;А. &nbsp;Роганова'' Функціональне програмування: Навчальний посібник для студентів вищих навчальних закладів -&nbsp;— М.: ГІНФО, 2002. -&nbsp;— 260 с. Стор. 14 п. 3.1. Ледачі і енергійні обчислення </ref>.
 
Як правило, нестрогий підхід реалізується у вигляді редукції графа. Нестрогое обчислення використовується за умовчанням в декількох чисто функціональних мовах, у тому числі [[Міранда (мова програмування) | Miranda]], [[Clean]] і [[Haskell]]. {{Ні АІ | 18 | 05 | 2009fact}}
 
=== ФП в нефункціональних мовах ===
Рядок 80 ⟶ 81:
Принципово немає перешкод для написання програм у функціональному стилі на мовах, які традиційно не вважаються функціональними, точно так само, як програми в [[Об'єктно-орієнтоване програмування | об'єктно-орієнтованому]] стилі можна писати на структурних мовах. Деякі імперативні мови підтримують типові для функціональних мов конструкції, такі як функції вищого порядку і спискові включення (list comprehensions), що полегшує використання функціонального стилю в цих мовах. Прикладом може бути програмування на мові Python]].
 
У мові [[Сі (мова програмування) | C]] покажчики на функцію в якості типів аргументів можуть бути використані для створення функцій вищого порядку. Функції вищого порядку і відкладена списковому структура реалізовані в бібліотеках [[С + +]]. У мові [[C Sharp | C #]] версії 3.0 і вище можна використовувати λ-функції для написання програми в функціональному стилі. У складних мовах, типу [[Алгол-68]], наявні засоби метапрограмування (фактично, доповнення мови новими конструкціями) дозволяють створити специфічні для функціонального стилю об'єкти даних і програмні конструкції, після чого можна писати функціональні програми з їх використанням. {{Немає АИ | 18 | 05 | 2009fact}}
 
== Стилі програмування ==
Рядок 107 ⟶ 108:
 
==== Підвищення надійності коду ====
Приваблива сторона обчислень без станів -&nbsp;— підвищення надійності коду за рахунок чіткої структуризації та відсутності необхідності відстеження побічних ефектів. Будь-яка функція працює тільки з локальними даними і працює з ними завжди однаково, незалежно від того, де, як і за яких обставин вона викликається. Неможливість мутації даних при користуванні ними в різних місцях програми виключає появу труднообнаружіваемих помилок (таких, наприклад, як випадкове присвоювання невірного значення глобальної змінної в імперативній програмі).
 
==== Зручність організації модульного тестування ====
Оскільки функція у функціональному програмуванні не може породжувати побічні ефекти, змінювати об'єкти не можна як усередині області видимості, так і зовні (на відміну від імперативних програм, де одна функція може встановити яку-небудь зовнішню змінну, що зчитується Другою функцією). Єдиним ефектом від обчислення функції є повертаний їй результат, і єдиний чинник, який впливає на результат -&nbsp;— це значення аргументів.
 
Таким чином, є можливість протестувати кожну функцію в програмі, просто обчисливши її від різних наборів значень аргументів. При цьому можна не турбуватися ні про виклик функцій в правильному порядку, ні про правильному формуванні зовнішнього стану. Якщо будь-яка функція в програмі проходить модульні тести, то можна бути впевненим у якості всієї програми. В імперативних програмах перевірка значення, що повертається функції недостатня: функція може модифікувати зовнішній стан, яке теж потрібно перевіряти, чого не потрібно робити в функціональних програмах <ref> [http://www.rsdn.ru/article/funcprog/fp.xml Ахмечет В . «Функціональне програмування для всіх»] </ref>.
 
==== Можливості оптимізації при компіляції ====
Рядок 118 ⟶ 119:
 
==== Можливості паралелізму ====
Ще однією перевагою функціональних програм є те, що вони надають найширші можливості для [[автоматичне розпаралелювання | автоматичного розпаралелювання]] обчислень. Оскільки відсутність побічних ефектів гарантовано, в будь-якому виклику функції завжди припустимо паралельне обчислення двох різних параметрів -&nbsp;— порядок їх обчислення не може вплинути на результат виклику.
 
=== Недоліки ===
Недоліки функціонального програмування випливають з тих же самих його особливостей. Відсутність присвоювання і заміна їх на породження нових даних призводять до необхідності постійного виділення та автоматичного звільнення пам'яті, тому в системі виконання функціональної програми обов'язковим компонентом стає високоефективний [[збирач сміття]]. Нестрога модель обчислень призводить до непередбачуваного порядку виклику функцій, що створює проблеми при введенні-виведенні, де порядок виконання операцій важливий. Крім того, очевидно, функції введення в своєму природному вигляді (наприклад, getchar із стандартної бібліотеки мови [[C (мова програмування) | C]]) не є чистими, оскільки здатні повертати різні значення для одних і тих же аргументів, і для усунення цього потрібні певні хитрощі.
 
Для подолання недоліків функціональних програм вже перші мови функціонального програмування включали не тільки чисто функціональні засоби, але і механізми імперативного програмування (привласнення, цикл, «неявний PROGN» були вже в LISPе). Використання таких засобів дозволяє вирішити деякі практичні проблеми, але означає відхід від ідей (і переваг) функціонального програмування і написання імперативних програм на функціональних мовами. У чистих функціональних мовах ці проблеми вирішуються іншими засобами, наприклад, в мові [[Haskell]] ввід-висновок реалізований за допомогою [[Монада_ (програмування) | монад]] -&nbsp;— нетривіальною концепції, запозиченої з теорії категорій.
 
== Виноски ==