Ruby - это функциональный язык?

88

Википедия говорит, что Ruby - это функциональный язык, но я не уверен. Почему или почему нет?

Эстебан Арая
источник
4
Наверное, потому что ваш вопрос очень короткий, хотя лично у меня с ним никаких проблем!
ljs 01
Уже есть хорошие ответы, так что просто в дополнение к ним пара материалов, в которых обсуждаются FP и Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
tokland 04
1
Если кому-то интересна эта тема, посмотрите это, и вы узнаете, как Ruby можно использовать функционально, каковы корни функционального программирования, почему Ruby не является функциональным языком, даже если он способен программировать функционально: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Ответы:

29

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

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

Тем не менее, на Ruby легко программировать и в нефункциональном стиле. Другой ключевой аспект функционального стиля - отсутствие состояния и наличие реальных математических функций, которые всегда возвращают одно и то же значение для заданного набора входных данных. Это можно сделать в Ruby, но не в языке, как в чем-то более строго функциональном, например, Haskell.

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

Майк Стоун
источник
4
Используя этот критерий, можно ли сказать, что Smalltalk функционален, потому что в нем есть блоки?
OscarRyz
Хороший ответ, но одна придирка - для функционального стиля функции высшего порядка не требуются строго. Например, вы можете достичь функционального стиля в Java (который не имеет функций первого класса / высшего порядка), определив объекты функций и составив их, чтобы получить тот же эффект, что и функция более высокого порядка.
mikera
2
Просто хочу заявить, что @peter спросил, Is ruby a functional language?и в прямом ответе просто нет. Ruby - это объектно-ориентированный язык с некоторыми функциональными возможностями.
Элиас Перес
58

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

Значимый вопрос: «Насколько Ruby поддается реализации тезиса функционального программирования?» Ответ - «очень плохо».

Я говорил об этом совсем недавно. Вот слайды.

Тони Моррис
источник
3
На слайдах, которые вы дали, не упоминалось, почему Ruby «очень плохо подходит для достижения тезиса FP». Почему C # более податлив, чем Java (хорошо, анонимные функции проще?)? Это потому, что в Ruby могут быть глобальные переменные?
kizzx2
7
Нет, на слайдах это не рассматривается, поскольку это довольно обширная тема. Например, рискуя чрезмерным упрощением, Ruby применяет модель оценки (вызов по значению), которая обеспечивает некомпозиционность программ. Последствия этого легко недооценить. Ruby также связан с идеей о том, что программа - это последовательность эффектов. Другими словами, Ruby изо всех сил старается сделать использование любой другой вычислительной модели трудным / внутренним. Надеюсь, этот короткий комментарий поможет.
Тони Моррис,
2
+1 за указание на неоднозначность классификации языков как функциональных. Черт, я написал функционал C!
Эли
1
Почему C # более податлив, чем Ruby?
dan_l 08
1
По сути, это ответ только для ссылки, поскольку он передает важную часть объяснения (фактически, все объяснение) внешней ссылке. Теперь, когда ссылка умерла, ответ стал бесполезным.
ivan_pozdeev
34

Ruby действительно поддерживает функции более высокого уровня (см. Array # map, inject, & select), но это все еще императивный объектно-ориентированный язык.

Одна из ключевых характеристик функционального языка - это то, что он избегает изменчивого состояния. В функциональных языках нет концепции переменной, как в Ruby, C, Java или любом другом императивном языке.

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

Майк
источник
3
Я согласен с большей частью вашего утверждения, однако я не согласен с тем, что «Функциональные языки не имеют концепции переменных, как в Java и т. Д.» В haskell вы можете использовать переменные в чистых функциях, вы даже можете назначить функцию переменной, самая большая разница в том, что после того, как переменная назначена, она не может быть впоследствии изменена.
HHC
6
HHC, по определению, переменная - это значение, которое может изменяться . Вы говорите о ценностях.
Scala Newb
Действительно, «неизменяемые переменные» Haskell - это просто постоянные функции без параметров (определений).
raindev
16

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

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

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

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

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

Во всяком случае, это мое ненаучное мнение.

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

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

Теперь это мое ненаучное мнение.

Крис Вест
источник
Я думаю, что вы можете сделать гораздо лучший аргумент в пользу того, чтобы называть Ruby функциональным, чем Java ... нет, Ruby не является строго функциональным, но в нем довольно легко использовать функциональный стиль ... и его коллега по нефункциональному стилю может легко изменить его обратно на нефункциональный
Майк Стоун
1
Да, Майк, если вы хотите кодировать в функциональном стиле, Ruby - это огромное улучшение по сравнению с Java. Я использовал Java только для того, чтобы преувеличить и довести до конца.
Крис Вест,
Итак, поскольку D имеет чистые функции, вы бы назвали D функциональным языком? digitalmars.com/d/2.0/function.html#pure-functions
Питер Бернс,
3
Многие считают Lisp и Scheme функциональными языками, в основном из-за повсеместного использования анонимных функций. И все же им не хватает гарантированных чистых функций. Ограничение этого термина языками, поддерживающими чистые функции, кажется слишком ограничительным.
skymt 02
13

Ruby должен будет соответствовать следующим требованиям, чтобы быть "НАСТОЯЩИМ" функциональным.

Неизменяемые значения: после того, как «переменная» установлена, ее нельзя изменить. В Ruby это означает, что переменные нужно рассматривать как константы. Не полностью поддерживается на языке, вам придется заблокировать каждую переменную вручную.

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

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

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

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

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

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

режим 'функциональный'

Элиас Перес
источник
2
Добро пожаловать. Я хотел бы предложить вам прочитать о функциональных языках. Lisp является прародителем всего функционального языка, ML (CAML) и Erlang / Elixir. Это действительно меняет ваш взгляд на вещи. Я далеко не эксперт, но постоянный студент, изучающий информатику, любит читать и изучать новые вещи.
Элиас Перес
Хорошо организованный ответ. Хотел бы получить дополнительное исследование того, насколько хорошо рубин поддерживает эти вещи. Я считаю, что в Ruby поддерживаются / возможны функции высшего порядка, каррирование и рекурсия, поправьте меня, если я ошибаюсь.
Майкл Дорст
9

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

Skymt
источник
8
предоставить доказательства
Миржан Иркегулов
4

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

пример:

"hello" .reverse () = "olleh", каждая строка является экземпляром строкового объекта и так далее, и так далее.

Прочтите здесь или здесь

камфлан
источник
Я никогда толком не понимал, как «все является объектом» делает Ruby более объектно ориентированным. Я согласен с тем, что Ruby - это в первую очередь объектно-ориентированный подход, но «все является объектом» на самом деле означает только отсутствие «примитивных» типов, что очень мало влияет на способность разработчика писать программы в стиле объектно-ориентированного программирования, учитывая, что существование примитивов Типы обычно просто означают, что есть четыре или пять типов, у которых нет никаких методов.
Майкл Дорст
4

Это зависит от вашего определения «функционального языка». Лично я считаю, что этот термин сам по себе довольно проблематичен, когда используется как абсолют. У «функционального языка» больше аспектов, чем просто языковых функций, и большинство из них зависит от того, откуда вы смотрите. Например, в этом отношении очень важна культура, окружающая язык. Поощряет ли это функциональный стиль? А как насчет доступных библиотек? Они побуждают вас использовать их функционально?

Например, большинство людей назвали бы Scheme функциональным языком. Но как насчет Common Lisp? Помимо проблемы с несколькими / одиночными пространствами имен и гарантированного исключения хвостового вызова (которое также поддерживается некоторыми реализациями CL, в зависимости от настроек компилятора), мало что делает Scheme как язык более подходящим для функционального программирования, чем Common Lisp, и тем не менее, большинство Lisp'ов не назовут CL функциональным языком. Зачем? Потому что окружающая его культура сильно зависит от императивных функций CL (например, макроса LOOP, который, вероятно, не понравится большинству программистов).

С другой стороны, программист на C вполне может считать CL функциональным языком. В конце концов, большая часть кода, написанного на любом диалекте Лиспа, безусловно, намного более функциональна по стилю, чем ваш обычный блок кода C. Точно так же Scheme - во многом императивный язык по сравнению с Haskell. Поэтому я не думаю, что когда-либо может быть однозначный ответ да / нет. Называть язык функциональным или нет - во многом зависит от вашей точки зрения.

Матиас Бенкард
источник
В каком смысле Haskell не является чисто функциональным языком? Или как насчет Миранды (менее известного языка функционального программирования)? course.cs.washington.edu/courses/cse505/99au/functional/… «Haskell - это стандартный чисто функциональный язык»,
Барлоп,
2

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

Я бы описал Ruby как объектно-ориентированный язык сценариев. Да, функции - это объекты первого класса (вроде), но это не делает их функциональным языком. ИМО, могу добавить.

JesperE
источник
4
Тип языка определяется поддерживаемыми им стилями программирования; это, в свою очередь, определяется его характеристиками. Первоклассные и анонимные функции = минимальное функциональное программирование. Ruby поддерживает объектно-ориентированное программирование, но не требует этого: вам никогда не нужно определять класс. Следовательно, мультипарадигма.
skymt 01
2

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

Функциональные языки программирования способны оптимизировать хвостовую рекурсию и выполнять такой код в постоянном пространстве. Некоторые реализации Ruby оптимизируют хвостовую рекурсию, другие - нет, но в целом реализации Ruby не требуют TCO. Смотрите, выполняет ли Ruby оптимизацию хвостового вызова?

Итак, если вы напишете какой-то функциональный стиль Ruby и полагаетесь на совокупную стоимость владения какой-то конкретной реализации, ваш код может оказаться очень неэффективным в другом интерпретаторе Ruby. Я думаю, что именно поэтому Ruby не является функциональным языком (как и Python).

састанин
источник
TCO интересен тем, что существенно меняет поведение программы. В некоторых случаях это не видно программе, но в других случаях, например, при отслеживании исключений. Следовательно, это не всегда подходящая оптимизация.
ioquatix
2

Строго говоря, не имеет смысла называть язык «функциональным»; большинство языков способны к функциональному программированию. Даже C ++ есть.

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

Последнее, возможно, является незначительной технической особенностью конкретной реализации и не имеет ничего общего с реальным языком. Компилятор x64 C # 4.0 оптимизирует хвостовую рекурсию, тогда как компилятор x86 не делает этого по какой-то глупой причине.

Синтаксический сахар обычно можно в той или иной степени обойти, особенно если в языке есть программируемый прекомпилятор (например, #define в языке C).

Возможно, было бы немного более осмысленным спросить: «Поддерживает ли язык __ императивное программирование?», И ответ, например, с Lisp, будет «нет».

Рей Миясака
источник
1

Пожалуйста, посмотрите начало книги: "A-Great-Ruby-eBook" . В нем обсуждается очень конкретная тема, которую вы задаете. На Ruby можно программировать разные типы. Если вы хотите программировать как функционально, вы можете это сделать. Если вы хотите программировать как императивно, вы можете это сделать. Насколько функциональна Ruby в конечном итоге - это вопрос определения. Пожалуйста, смотрите ответ пользователя camflan.

Лео Леопольд Герц 준영
источник