Чи є Ruby функціональною мовою?


88

У Вікіпедії сказано, що Ruby - це функціональна мова, але я не переконаний. Чому чи чому б ні?


4
Можливо, тому, що ваше запитання дуже коротке, хоча особисто я з ним не маю жодних проблем!
ljs

Вже є хороші відповіді, тож, щоб доповнити їх, пара вмісту, що обговорює FP та Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
Tokland

1
Якщо когось цікавить ця тема, перегляньте це, і ви дізнаєтесь, як ruby ​​можна використовувати функціонально, які корені функціонального програмування, чому ruby ​​не є функціональною мовою, навіть якщо він здатний програмувати функціонально: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Відповіді:


29

Я абсолютно точно думаю, що ви можете використовувати функціональний стиль у Ruby.

Одним з найбільш важливих аспектів, який можна запрограмувати у функціональному стилі, є якщо мова підтримує функції вищого порядку ... що робить Рубі.

Тим не менш, також легко програмувати на Ruby в нефункціональному стилі. Іншим ключовим аспектом функціонального стилю є відсутність стану, а реальні математичні функції, які завжди повертають одне і те ж значення для заданого набору входів. Це можна зробити в Ruby, але це не застосовується в мові, як щось більш суворо функціональне, як Haskell.

Так, так, він підтримує функціональний стиль, але це також дозволить вам програмувати і в нефункціональному стилі.


4
Використовуючи ці критерії, чи могли б ви сказати, що Smalltalk функціональний, оскільки має блоки?
OscarRyz

Хороша відповідь, але одна штука - функції вищого порядку не є суворо необхідними для функціонального стилю. Наприклад, ви можете досягти функціонального стилю в Java (яка не має функцій першого класу / вищого порядку), визначивши об’єкти функцій та склавши їх, щоб отримати такий самий ефект, як функція вищого порядку.
mikera

2
Просто, хочу сказати, що @peter запитав, Is ruby a functional language?і в прямій відповіді це просте ні. Ruby - це об’єктно-орієнтована мова з деякими функціональними особливостями.
Еліас Перес

58

Чи є мова функціональною, чи ні - це неважливо. Функціональне програмування - дипломна робота, яку найкраще пояснили Філіп Уодлер (Суть функціонального програмування) та Джон Хьюз (Чому функціональне програмування має значення).

Значуще запитання: "Наскільки Рубі піддається досягненню тези про функціональне програмування?" Відповідь "дуже погано".

Нещодавно я говорив про це. Ось слайди.


3
У слайдах, які ви давали, не згадувалося, чому Рубі "дуже погано піддається досягненню тези про ФП". Чому C # придатніший за Java (добре, простіші анонімні функції?)? Це тому, що ви можете мати глобальні змінні в Ruby?
kizzx2

7
Жодні слайди не вдаються в цю деталь, оскільки це досить велика тема. Наприклад, загрожує надмірним спрощенням, Ruby застосовує модель оцінки (call-by-value), яка забезпечує некомпозиційність програм. Наслідки цього легко можна недооцінити. Рубі також одружена з ідеєю, що програма - це послідовність ефектів. Тобто, Рубі робить все, щоб ускладнити / неможливо застосувати будь-яку іншу обчислювальну модель. Сподіваюсь, цей короткий коментар допоможе.
Тоні Морріс,

2
+1 за вказівку на неоднозначність класифікації мов як функціональних. Чорт, я написав функціонал C!
Елі,

1
Чому C # піддається більше, ніж Ruby?
dan_l

1
Фактично відповідь лише на посилання, оскільки вона передає критичну частину пояснення (фактично все пояснення) на зовнішнє посилання. Тепер, коли посилання загинуло, відповідь стала марною.
ivan_pozdeev

34

Ruby дійсно підтримує функції вищого рівня (див. Карта масиву #, вводити та вибирати), але все ще є обов’язковою, об’єктно-орієнтованою мовою.

Однією з ключових характеристик функціональної мови є те, що вона уникає мінливого стану. Функціональні мови не мають поняття змінної, як це було б у Ruby, C, Java чи будь-якій іншій імперативній мові.

Ще однією ключовою характеристикою функціональної мови є те, що вона зосереджена на визначенні програми з точки зору "що", а не "як". Під час програмування на мові OO ми пишемо класи та методи, щоб приховати реалізацію ("як") від "what" (ім'я класу / методу), але врешті-решт ці методи все-таки записуються з використанням послідовності операторів. У функціональній мові ви не вказуєте послідовність виконання, навіть на найнижчому рівні.


3
Я погоджуюсь з більшістю вашого твердження, однак, я не згоден з приводу "Функціональні мови не мають поняття змінних, як це було б у Java тощо". У haskell ви можете використовувати змінні в чистих функціях, ви навіть можете призначити функцію змінній, найбільша різниця полягає в тому, що після присвоєння змінної вона не може бути змінена згодом.
HHC

6
HHC, за визначенням, змінна - це величина, яка може змінюватися . Ви говорите про цінності.
Скала Ньюб

Справді, "немодифіковані змінні" Хаскелла - це просто постійні функції без параметрів (визначень).
raindev

16

Я вважаю, що підтримка або можливість програмування мовою у функціональному стилі не є функціональною мовою.

Я навіть можу написати Java - код в функціональному стилі , якщо я хочу образити моїх колег і , і я сам кілька місяців тижні на.

Наявність функціональної мови - це не тільки те, що ви можете зробити, наприклад, функції вищого порядку, першокласні функції та каррі. Йдеться також про те, що ви не можете зробити, як побічні ефекти в чистих функціях.

Це важливо, оскільки це велика частина причини, чому функціональні програми або функціональний код у generel легше міркувати. І коли про код легше міркувати, помилки стають дрібнішими і спливають на концептуальну поверхню, де їх можна виправити, що, в свою чергу, дає менше коду помилок.

Ruby в своїй основі є об’єктно-орієнтованим, тому, хоча він має досить хорошу підтримку функціонального стилю, сам по собі він не є функціональною мовою.

Це все одно моя ненаукова думка.

Редагувати: Оглянувши ретроспективу та враховуючи чудові коментарі, я отримав цю відповідь до цього часу, я думаю, що об’єктно-орієнтоване порівняно з функціональним порівнянням - це яблука та апельсини.

Справжній відмінність полягає в тому, щоб бути непорушним у виконанні чи ні. Функціональні мови мають вираз основною лінгвістичною конструкцією, і порядок виконання часто не визначений або визначений як ледачий. Можливе суворе виконання, але застосовується лише за потреби. Мовою, що не відповідає вимогам, за замовчуванням є строге виконання, і хоча можливе ледаче виконання, це часто буває важко робити, і це може мати непередбачувані результати у багатьох крайових випадках.

Зараз це моя ненаукова думка.


Я думаю, ви можете зробити набагато кращий випадок для виклику Ruby функціональним, ніж Java .... ні, Ruby не є суто функціональним, але використовувати функціональний стиль у ньому досить просто ... і нефункціональний колега може легко змінити його на нефункціональний
Mike Stone

1
Так, Майк, якщо ти хочеш кодувати у функціональному стилі, тоді Ruby - це величезне покращення порівняно з Java. Я використовував Java лише для того, щоб перебільшити і забити суть додому.
Chris Vest

Отже, оскільки D має чисті функції, ви б назвали D функціональною мовою? digitalmars.com/d/2.0/function.html#pure-functions
Пітер Бернс,

3
Багато людей вважають мови Lisp та Scheme функціональними мовами, значною мірою через поширене використання анонімних функцій. І все ж їм бракує гарантованих чистих функцій. Обмеження терміна мовами, які підтримують чисті функції, здається занадто обмежувальним.
skymt

13

Ruby повинен відповідати наведеним нижче вимогам, щоб бути "Справді" функціональним.

Незмінні значення: після встановлення “змінної” її неможливо змінити. У Ruby це означає, що вам ефективно потрібно обробляти змінні як константи. Мова не повністю підтримується мовою, вам доведеться заморозити кожну змінну вручну.

Відсутність побічних ефектів: при передачі заданого значення функція завжди повинна повертати однаковий результат. Це поєднується з незмінними значеннями; функція ніколи не може приймати значення і змінювати його, оскільки це може спричинити побічний ефект, який є дотичним до повернення результату.

Функції вищого порядку: це функції, які дозволяють функції як аргументи або використовують функції як повернене значення. Це, безперечно, одна з найважливіших особливостей будь-якої функціональної мови.

Каррінг: увімкнений функціями вищого порядку, каррінг - це перетворення функції, яка приймає кілька аргументів, у функцію, яка приймає один аргумент. Це поєднується із частковим застосуванням функції, яке перетворює багатоаргументну функцію у функцію, яка приймає менше аргументів, ніж раніше.

Рекурсія: циклічне виклик функції зсередини. Коли у вас немає доступу до змінних даних, рекурсія використовується для створення та ланцюжка побудови даних. Це пояснюється тим, що цикл не є функціональним поняттям, оскільки він вимагає передачі змінних для збереження стану циклу в даний момент часу.

Ледача оцінка, або відкладена оцінка: затягування обробки значень до моменту, коли це насправді потрібно. Якщо, як приклад, у вас є якийсь код, який створив список чисел Фібоначчі з увімкненим методом лінивого оцінювання, це насправді не буде оброблятися і обчислюватися, поки одне зі значень у результаті не буде потрібно іншою функцією, наприклад, путами.

Пропозиція (Тільки думка) Мені було б здорово мати якесь визначення, щоб мати modeдирективу для оголошення файлів з функціональною парадигмою,

режим "функціональний"


2
Будь ласка. Я хотів би запросити вас прочитати про функціональні мови. Лісп - дідусь і бабуся всіх функціональних мов, ML (CAML) та Erlang / Elixir. Це насправді змінює ваш погляд на речі. Я далеко не фахівець, але постійний студент інформатики любить читати та вивчати нові речі.
Еліас Перес

Добре організована відповідь. Я б хотів додатково дослідити, наскільки добре рубін підтримує ці речі. Я вважаю, що функції вищого порядку, каррінг та рекурсія підтримуються / можливі в ruby, будь ласка, виправте мене, якщо я помиляюся.
Майкл Дорст,


4

Ruby - це об'єктно-орієнтована мова, яка може підтримувати інші парадигми (функціональні, імперативні тощо). Однак, оскільки все в Ruby є об'єктом, це насамперед мова OO.

приклад:

"hello" .reverse () = "olleh", кожен рядок є екземпляром рядкового об'єкта тощо і так далі.

Прочитайте тут чи тут


Я ніколи насправді не розумів, як "все - це об'єкт" робить Рубі більше ОО. Я згоден з тим, що Ruby - це в основному ОО, але "все є об'єктом" насправді означає лише відсутність "примітивних" типів, що дуже мало впливає на здатність розробника писати програми в стилі ОО, враховуючи те, що існування примітиву типи загалом просто означає, що існує чотири-п’ять типів, які не мають жодних методів.
Майкл Дорст,

4

Це залежить від вашого визначення “функціональної мови”. Особисто я думаю, що сам термін є досить проблематичним, якщо його використовувати як абсолютний. Це більше аспектів, як бути “функціональною мовою”, ніж просто мовні особливості, і більшість залежать від того, звідки ви дивитесь. Наприклад, культура, що оточує мову, є досить важливою в цьому плані. Чи заохочує це функціональний стиль? А як щодо доступних бібліотек? Чи заохочують вони вас використовувати їх функціонально?

Наприклад, більшість людей називали б схему функціональною мовою. Але як щодо Common Lisp? Окрім проблеми з кількома / єдиними іменами та гарантованого усунення хвостового виклику (який підтримують також деякі реалізації CL, залежно від налаштувань компілятора), не так багато, що робить Scheme як мову більш придатною для функціонального програмування, ніж Common Lisp, і все ж більшість Lispers не називали б CL функціональною мовою. Чому? Оскільки культура, яка його оточує, сильно залежить від обов’язкових особливостей CL (наприклад, як макрос LOOP, наприклад, на який, напевно, бідкається більшість Schemers).

З іншого боку, програміст C цілком може вважати CL функціональною мовою. Більшість кодів, написаних на будь-якому діалекті Lisp, безумовно, набагато функціональніші за стилем, зрештою, як ваш звичайний блок коду C. Так само, Scheme є дуже необхідною мовою порівняно з Haskell. Тому я не думаю, що коли-небудь може бути чітка відповідь так / ні. Чи називати мову функціонально чи ні, сильно залежить від вашої точки зору.


Яким чином Хаскелл не є суто функціональною мовою? Або як щодо Міранди (менш відомої мови функціонального програмування)? courses.cs.washington.edu/courses/cse505/99au/functional/… "Haskell - це стандартна чисто функціональна мова,"
barlop,

2

Я думаю, що Ruby насправді не є багатомовною парадигмою. Мультипарадигма, як правило, використовується людьми, які хочуть позначити свою улюблену мову як щось корисне у багатьох різних сферах.

Я б описав, що Ruby є об'єктно-орієнтованою мовою сценаріїв. Так, функції - це першокласні об’єкти (начебто), але це насправді не робить їх функціональною мовою. IMO, я можу додати.


4
Тип мови визначається стилями програмування, які він підтримує; це, в свою чергу, визначається його особливостями. Першокласні та анонімні функції = мінімальне функціональне програмування. Ruby підтримує програмування OO, але не вимагає цього: вам ніколи не потрібно визначати клас. Отже, мультипарадигма.
skymt

2

Рекурсія поширена у функціональному програмуванні. Майже будь-яка мова підтримує рекурсію, але рекурсивні алгоритми часто неефективні, якщо відсутня оптимізація хвостових викликів (TCO).

Функціональні мови програмування здатні оптимізувати рекурсію хвоста і можуть виконувати такий код у постійному просторі. Деякі реалізації Ruby оптимізують рекурсію хвоста, інші ні, але загалом реалізації Ruby не вимагають TCO. Подивіться, чи виконує Ruby оптимізацію виклику хвоста?

Отже, якщо ви пишете якийсь функціональний стиль Ruby і покладаєтесь на TCO певної реалізації, ваш код може бути дуже неефективним в іншому інтерпретаторі Ruby. Думаю, саме тому Ruby не є функціональною мовою (як і Python).


TCO цікавий, оскільки він суттєво змінює поведінку програми. У деяких випадках це не видно програмі, але в інших випадках воно є, наприклад, зворотні сліди винятків. Тому це не завжди є відповідною оптимізацією.
ioquatix

2

Власне кажучи, немає сенсу описувати мову як «функціональну»; більшість мов здатні до функціонального програмування. Навіть C ++ є.

Функціональний стиль - це більш-менш підмножина імперативних особливостей мови, що підтримується синтаксичним цукром та деякими оптимізаціями компілятора, такими як незмінність та згладжування рекурсії хвоста,

Останнє, безперечно, є незначною технічною специфікою для реалізації та не має нічого спільного з фактичною мовою. Компілятор x64 C # 4.0 виконує оптимізацію рекурсії хвоста, тоді як x86 не робить це з якоїсь дурної причини.

Синтаксичний цукор зазвичай можна в тій чи іншій мірі опрацювати, особливо якщо мова має програмований попередній компілятор (тобто C #define).

Може бути дещо більш значущим запитати: "чи підтримує мова __ імперативне програмування?", А відповідь, наприклад, з Lisp, "ні".


1

Будь ласка, погляньте на початок книги: "A-Great-Ruby-eBook" . У ньому обговорюється дуже конкретна тема, яку ви задаєте. У Ruby ви можете робити різні типи програмування. Якщо ви хочете програмувати як функціонально, ви можете це зробити. Якщо ви хочете програмувати як імперативно, ви можете це зробити. Це питання визначення, наскільки функціональний Ruby врешті-решт. Перегляньте відповідь користувача camflan.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.