it-swarm.com.ru

Почему Python не очень хорош для функционального программирования?

Я всегда думал, что функциональное программирование может быть сделано на Python. Таким образом, я был удивлен, что Python не получил большого упоминания в this вопросе, и когда он упоминался, он обычно не был очень позитивным. Однако для этого не было приведено много причин (упоминалось отсутствие сопоставления с образцом и алгебраических типов данных). Поэтому мой вопрос: почему Python не очень хорош для функционального программирования? Есть ли больше причин, чем отсутствие сопоставления с образцом и алгебраические типы данных? Или эти концепции настолько важны для функционального программирования, что язык, который их не поддерживает, можно классифицировать только как второсортный язык функционального программирования? (Имейте в виду, что мой опыт функционального программирования весьма ограничен.)

315
David Johnstone

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

Лучший аргумент против функционального программирования в Python заключается в том, что варианты использования с императивным/OO тщательно рассматриваются Guido, в то время как сценарии использования функционального программирования не. Когда я пишу императивный Python, это один из самых красивых языков, которые я знаю. Когда я пишу функциональный Python, он становится таким же уродливым и неприятным, как ваш обычный язык, у которого нет BDFL .

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

Вот функциональные вещи, которые я пропускаю в Python:


  • Отсутствие сопоставления с образцом и хвостовая рекурсия означают, что ваши базовые алгоритмы должны быть обязательно написаны. Рекурсия уродливая и медленная в Python.
  • Небольшая библиотека списков и отсутствие функциональных словарей означают, что вам придется писать много вещей самостоятельно.
  • Отсутствие синтаксиса для карри или композиции означает, что стиль без точек почти такой же пунктуации, как и явно передаваемые аргументы.
  • Итераторы вместо ленивых списков означают, что вы должны знать, хотите ли вы эффективность или постоянство, и разбрасывать вызовы list вокруг, если вы хотите постоянство. (Итераторы используются один раз)
  • Простой императивный синтаксис Python, наряду с его простым синтаксическим анализатором LL1, означает, что лучший синтаксис для выражений if и лямбда-выражений в принципе невозможен. Гвидо так нравится, и я думаю, что он прав.
379
Nathan Shively-Sanders

Гвидо имеет хорошее объяснение этого здесь . Вот самая важная часть:

Я никогда не думал, что Python находится под сильным влиянием функциональных языков, независимо от того, что люди говорят или думают. Я был намного лучше знаком с императивными языками, такими как C и ALGOL 68, и хотя я сделал функции первоклассными объектами, я не рассматривал Python как функциональный язык программирования. Однако ранее было ясно, что пользователи хотят делать гораздо больше со списками и функциями.

...

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

И наконец, даже несмотря на то, что за эти годы был введен ряд функциональных функций программирования, Python все еще не хватает определенных функций, присутствующих в "настоящих" функциональных языках программирования. Например, Python не выполняет определенные виды оптимизации (например, хвостовая рекурсия). В целом, поскольку Python чрезвычайно динамичен, невозможно выполнить оптимизацию во время компиляции, известную из функциональных языков, таких как Haskell или ML. И это нормально.

Я вытащил две вещи из этого:

  1. Создатель языка не считает Python функциональным языком. Таким образом, можно увидеть функционально-функциональные особенности, но вряд ли вы увидите что-либо, что является окончательно функциональным.
  2. Динамическая природа Python запрещает некоторые оптимизации, которые вы видите в других функциональных языках. Конечно, LISP так же динамичен (если не более динамичен), как и Python, так что это только частичное объяснение.
98
Jason Baker

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

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

  2. Если это заявления, а не выражения. Это означает, что, между прочим, у вас не может быть лямбды с If внутри. (Это исправлено троичными в Python 2.5, но выглядит уродливо.)

  3. Гвидо угрожает убрать карту, отфильтровать и уменьшить время от времени

С другой стороны, python имеет лексические замыкания, лямбды и списки (которые на самом деле являются "функциональной" концепцией, признает ли это Гвидо). Я много программирую в "функциональном стиле" на Python, но вряд ли скажу, что он идеален.

50
Jacob B

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

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

21
Konrad Rudolph

Позвольте мне продемонстрировать фрагмент кода, взятый из ответа на "функционал" вопрос по Python на SO

Python:

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = itertools.chain.from_iterable(itertools.imap(kidsFunc, layer))
  return layer

Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation

Основное отличие состоит в том, что стандартная библиотека Haskell имеет полезные функции для функционального программирования: в этом случае iterate, concat и (!!)

16
yairchu

Одна вещь, которая действительно важна для этого вопроса (и ответов), заключается в следующем: что, черт возьми, такое функциональное программирование и каковы его самые важные свойства? Я постараюсь дать свой взгляд на это:

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

Функциональное программирование очень похоже на это; вы ничего не меняете, вы просто оцениваете уравнение (или, в данном случае, "программа") и выясняете, каков ответ. Программа все еще там, без изменений. То же самое с данными.

Я бы оценил следующее как наиболее важные особенности функционального программирования: а) ссылочная прозрачность - если вы оцениваете одно и то же утверждение в другое время и в другом месте, но с теми же значениями переменных, оно все равно будет означать то же самое. б) без побочных эффектов - независимо от того, как долго вы смотрите на доску, уравнение, на которое другой парень смотрит на другую доску, не изменится случайно. в) функции тоже значения. которые могут быть переданы и применены, или к другим переменным. г) состав функции, вы можете сделать h = g · f и, таким образом, определить новую функцию h(..), которая эквивалентна вызову g (f (..)).

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

Теперь, если вы пройдете через python и ​​проверите, насколько хорошо язык и библиотеки поддерживают и гарантируют эти аспекты, - вы уже в пути, чтобы ответить на свой вопрос.

14
xeno

Python - это почти функциональный язык. Это "функциональный лайт".

У него есть дополнительные функции, поэтому для некоторых он недостаточно чист.

В ней также отсутствуют некоторые функции, поэтому для некоторых она не является полной.

Недостающие функции относительно легко написать. Проверьте сообщения вроде this на FP в Python.

11
S.Lott

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

8
Dvd Avins

В дополнение к другим ответам, одна из причин Python и ​​большинства других мультипарадигмальных языков не очень подходит для настоящего функционального программирования, потому что их компиляторы/виртуальные машины/среды выполнения не поддерживают функциональную оптимизацию. Такая оптимизация достигается компилятором, понимающим математические правила. Например, многие языки программирования поддерживают функцию или метод map. Это довольно стандартная функция, которая принимает функцию в качестве одного аргумента и итеративную в качестве второго аргумента, а затем применяет эту функцию к каждому элементу в итерируемой.

В любом случае оказывается, что map( foo() , x ) * map( foo(), y ) - это то же самое, что map( foo(), x * y ). Последний случай на самом деле быстрее, чем первый, потому что первый выполняет две копии, где последний выполняет одну.

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

4
user2074102