Как стать автором
Обновить

Комментарии 100

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

  • Сперва в императивном абы как стиле
  • Потом в объектном
  • Потом в функциональном.


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

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

В целом это отличный пойнт — у всего есть границы и ниши применимости. Есть вещи, при которых ООП реально более удобен, есть вещи, для которых удобнее функциональный подход, а для некоторых удобнее декларативный.

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

Как считаете?
Я согласен, что посыл должен звучать, как — 'Вы должны знать прежде всего ооп, а уже когда Вы его реально поймете, тогда будет просто великолепно забивать голову чем-то другим, особенно если Вы склонны к алгебре, уравнениям и теориям множеств и хотите писать компиляторы'. Но дело в том, что те кто хвалит фп, как например Вы, имели дело с ним только в минимальном количестве и естественно пример был подогнан под него. И даже это не страшно. самое страшное что люди его хвалят за… как бы сказать… способность работать в асинхронном стиле.
Сделай это — потом это — если не смог, то — это — или это —

Так вот эта асинхронщина или параллельность, тоже никакого отношения к фп не имеет. Это просто обычная библиотека реализующая шаблоны спецификация, комманда, обсервер и прочие. И почему-то мне кажется, что такой подход впервые был применен в ооп, а затем его уже стали выдавать как фичу фп.
Ну раз Вы знаете, в каком количестве я имел опыт с «ФП», какое отношение имеет «ФП» к «асинхронщине» и «параллельности», и что нужно знать «прежде всего» — то Вам, конечно, виднее :)
Я неудачно выразился. Конкретно Вас я упомянул в контексте что где-то на школьном уровне Вам показалось что фп это круто, так как Вы описывали, какой-то выдуманный парсер. Также не понятно что Вам кажется странным по поводу асинхронности и параллельности? Даже в статье идет речь об этом, да и сегодня, мне кажется никто фп не продвигает, а продвигают все фрп. Если Вы реально говорите о школьной программе чистого фп, то я извиняюсь. И правильно, давайте скажите что я не прав сказав что нужно учить ооп! А то я знаю, я предполагаю… Чувство что Вы хотите на меня переложить свою неосведомленность, придумывая безумные выражения, что я читаю Ваши слова и уменя картина вырисовывается, что я прям монстр какой-то.
На мой взгляд, плюсы ооп в том, что он повторяет абстракции реального мира.
Допустим…
шаблоны спецификация, комманда, обсервер и прочие.
Вы наверное это подразумевали под «абстракции реального мира»? Как мне понять, например, что такое «шаблон команда» на примере со зверушками?
Я даже не знаю что Вы хотите услышать… то ли надеетесь, что я целую статью напишу, а возможно ждете что-то, типа «в муравейнике, муравей прораб выдает всем поручения, запечатанные в конверты… и т.д.»?
Пытаюсь понять что же вы имели в виду своей первой фразой.

А также намекнуть, что в ООП зачастую используются абстракции, у которых нету аналогов в реальном мире (но конечно можно придумать поясняющие примерчики в стиле «для дошколят», навроде примера про муравьев).

Что значит для дошколят? Если Вам просто слышаться как глупо, то можете нервную систему представить, электросеть. А то что можно придумать, Вас не напрягает что Вы на английском пишите? Почему не на китайском? Почему не на клингонском? Скорее всего из-за того что Вы не любите напрягаться, а сейчас фразой о школьниках, просто сумничали. И все дело в том что ооп и должно работать с абстракциями которыми мы мыслим. Если Вы пишите по другому, то это означает только одно, Вы пишите в структурном стиле. У Вас массивы, коллекции, и объекты, вместо абстракций. Да я тоже так частенько пишу, но в такие моменты я не считаю что пишу на ооп.
Что значит для дошколят?
Я не хотел никого обидеть. Просто примеры подобного рода (прораб раздает конвертики с указаниями — это мол пример шаблона «команда») по сути своей не более чем примеры. Причем очень поверхностные и наивные, потому и годящиеся разве что при обучении.

Кстати применительно к ФП тоже можно придумать уйму подобных примеров. Скажем монады можно мысленно представить как эдакие картонные коробочки

И все дело в том что ооп и должно работать с абстракциями которыми мы мыслим. Если Вы пишите по другому, то это означает только одно, Вы пишите в структурном стиле.
Подождите, подождите… Вы хотите сказать, что когда мы «пишем в структурном стиле», то мы работаем с какими-то другими, немыслимыми абстракциями?

ЗЫ: «абстракции реального мира» — в реальном мире нету абстракций; т.е. абстракция это по определению плод нашего разума, результат обобщения, поиска общих связей и отбрасывания несущественных.
Вы реально уже одолели своими догадками. Пример с прорабом слишком прост. Когда Вам на физкультуре говорили — бери мяч и кидай его в корзину, Вы что простите говорили? Что это слишком просто, что в мире нет понятия кидай, а есть совокупность законов физики? Вы либо хотите чтобы люди в этой теме прекратили говорить о ооп, так как Вы в каждом коменте пишите, да это вообщене так и это тоже не так и просите рассказать Вам, при этом сами только предположения пишите. И знаете, для для меня слово человек, это абстракция из реального мира. Мир в котором живу я, есть люди. А если, простите придираться к словам, то что значит, подождите подождите, Вас заклинило?
По теме расписал свое мнение в другой ветке.

Вы либо хотите чтобы люди в этой теме прекратили говорить о ооп
Нет, я лишь хочу, чтобы люди перестали приписывать ООП те качества, которых у него нет.

Кстати, вот Вы пишете:
я упомянул в контексте что где-то на школьном уровне Вам показалось что фп это круто
Если Вы реально говорите о школьной программе
а сейчас фразой о школьниках
Когда Вам на физкультуре говорили
Почему Вы постоянно вспоминаете школу, приводите школьные примеры?

Извините, что встреваю в вашу дискуссию, но, простите, вы на каком языке пишите? Слова, вроде бы, из русского…

На самом деле немного не так. «Абстракции реального мира» это те понятия, которые мы выделяем в окружающем мире. Выделяем понятия предметной области и называем это бизнес-логикой. Выделяем технические понятия и называем это протоколами и шаблонами. Но практически всё это объекты с состоянием и поведением, по которым мы их и различаем.
скиньте ссылку на курс, пожалуйста.
>> На мой взгляд, плюсы ооп в том, что он повторяет абстракции реального мира.
А где в реальном мире найти примеры для инкапсуляции, наследования, методов/сообщений, интерфейсов, абстрактных классов, виртуальных методов и т.п.?
Интерфейсы/сообщения — практически везде. Инкапсуляция, соответственно тоже (ее, кстати нужно рассматривать не как атрибут, а как цель ООП). А все остальное вами перечисленное относится не к канонам ООП, а к деталям реализации.
Раз уж выше упомянули зверушек…

Интерфейсы/сообщения — практически везде.
Какие интрефейсы реализует Кот?
Какие сообщения сообщения он может посылать, принимать?
Когда кот ест… он принимает сообщения от еды или посылает их еде?
Кот и кошка — это объекты разных классов или одного?
Когда кошка рожает котят… это наследование? Прототипное? Есть ли тут классы?

Инкапсуляция, соответственно тоже
Приведите конкретные примеры что же инкапсулирует кошка.
Какие интрефейсы реализует Кот?
Софт пишется не для абстрактных задач, а для конкретных. Точно так и не бывает абстрактных котов которые «сами по себе»: для хозяина кот существует не «просто так», а для каких-то конкретных целей.

Если вы купили кота чтоб его кормить и слушать как он мяукает, то для вас он реализует интерфейсы «есть» и «мяукать».
Если вы купили кота для того, чтобы он ловил мышей — он реализует интерфейс «ловить мышей».
Вот вам и инкапсуляция — при покупке кота вы не думаете, как он устроен на биологическом/физическом уровне. Вас интересует только интерфейс, который он предоставляет. Один и тот же кот может устроить как покупателя кота-мяукателя, так и покупателя кота-хищника.

Какие сообщения сообщения он может посылать, принимать?
Когда определитесь что конкретно вы моделируете, и какие конкретно интерфейсы вам нужны от кота, тогда же станет понятно какие сообщения он принимает/отправляет.

Когда кот ест… он принимает сообщения от еды или посылает их еде?
Опять же, зависит от того, что конкретно вы пытаетесь моделировать и в каких пределах. Абстрактный кот ничего не отправляет и не принимает. Как только от абстракции вы перейдете к конкретике, тогда и прояснится ситуация с сообщениями.

Кот и кошка — это объекты разных классов или одного?
Опять-таки зависит от контекста. К слову, классы и наследование вовсе не являются обязательными для объектного подхода.

Когда кошка рожает котят… это наследование? Прототипное? Есть ли тут классы?
И опять все зависит от контекста.
Например, если вы используете кошку исключительно для производства котят на продажу, то кошка — это некий порождающий объект (а-ля Фабрика), а котята — это Товары. В этом контексте оказывается что у котят больше общего с айфонами или буханками хлеба, чем с порождающими их кошками. А у кошки больше общего с фабриками Foxconn и пекарнями, чем с котятами.
То, что в биологии они относятся к одному виду/классу, вовсе не означает что так будет в любом другом контексте.
Ох… Я прекрасно понимаю что можно построить модель кота(кошки) в рамках ООП. И будет она, разумеется, зависеть от контекста… Мы решим какие объекты у нас, разобьем на классы, завезем наследование, опишем реакцию объектов на сообщения и прочее… Это все понятно.

Проблема в том, что, с одной стороны, мы не можем описать (моделировать) реальный мир посредством ООП с высокой точностью. Для наглядности приведу известную «проблему»: лопата копает яму или яма копается лопатой? Т.е. как бы мы ООП не любили, но взаимодействия объектов в нем однонаправленные: один объект инициирует действие (посылает сообщения, вызывает метод), второй объект его обрабатывает и попутно изменяет свое состояние, возвращает ответ… Взаимодействие всегда(!) асимметричное. Поэтому иногда в наших программах лопата копает яму, в другой раз яма копается лопатой, в третий раз у нас есть рабочий который копает яму и пользует лопату… Как Вы правильно заметили, все зависит от контекста.

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

Например, имеется ли в реальном мире объект, умеющий в ICloneable? Чтобы так взял и скопировал сам себя? Или где найти в реальном мире аналог для шаблона strategy? Или вот где взять Enumeration? А шаблон visitor? И т.д. и т.п.

В общем целом, при написания софта (для конкретных задач!) помимо моделирования сущностей реально мира нам приходится описывать и абстрактные конструкции.

Так вот ООП не всегда удобен для первого как минимум ввиду асимметричного взаимодействия объектов. А еще я искренне не понимаю, с какой стати «композиция функций» сложнее, чем, скажем, «декорирование объекта».
мы не можем описать (моделировать) реальный мир посредством ООП с высокой точностью
А как вы меряете, эту самую точность с которой можем и не можем описать? Как вы определяете границу?
Ну и мне непонятно почему же таки не можем: при моделировании мы сами решаем какая точность модели нам нужна. Другое дело что ООП может вносить дополнительную сложность, и если исходная сложность системы которую мы пытаемся моделировать изначально очень велика, то конечная модель может выйти монструозной. Но в любом случае от inherent complexity не спасает ни ООП, ни ФП, ни что либо еще.
Ну и плюс есть люди с ООП головного мозга, очень склонные к оверинжинирингу.

Для наглядности приведу известную «проблему»: лопата копает яму или яма копается лопатой?
Почему-то людям часто кажется что где-то должно быть описано единственно правильное решение этой проблемы. А его нет, и быть не может.

Понимаете, ООП и языки программирования это средства коммуникации. Если ваша архитектура/домен явно не навязывает вам ответ на этот вопрос, значит вы сами вольны выбрать тот ответ, который вам удобнее. Который выглядит более естественным, делает вашу коммуникацию легче, а ментальную нагрузку — ниже. ООП не решит это за вас, потому что нет единого решения.

Поэтому иногда в наших программах лопата копает яму, в другой раз яма копается лопатой, в третий раз у нас есть рабочий который копает яму и пользует лопату… Как Вы правильно заметили, все зависит от контекста.
Вы так говорите, как будто это что-то плохое. Если у взаимодействия ямы и лопаты есть три разных контекста, значит это три разных задачи. И у них будет три разных решения. Не совсем понимаю почему вы считаете это недостатком, и какие предлагаете альтернативы.

Например, имеется ли в реальном мире объект, умеющий в ICloneable? Чтобы так взял и скопировал сам себя? Или где найти в реальном мире аналог для шаблона strategy? Или вот где взять Enumeration? А шаблон visitor? И т.д. и т.п.
То, что ООП хорошо позволяет моделировать объекты реального мира, вовсе не означает что ООП обязано моделировать исключительно объекты реального мира. Иногда с помощью ООП моделируют в том числе и объекты из мира программирования. Впрочем их тоже можно считать объектами «реального мира» — мира разработки ПО. Он ведь вполне реален для разработчиков.
И опять-таки, бывает ООП головного мозга вызванное например Java, где часто классы/объекты создают на каждый чих, и в итоге за абстрактными фабриками синглтонов деревьев не видно леса. Но это проблема отдельных языков/разработчиков, а не объектного подхода в целом.

А ваши претензии насчет ассиметричности взаимодействия объектов мне не очень понятны. Необходимость решать кто инициирует копание (яма, лопата, или рабочий) — это единственный недостаток, или есть другие? Есть есть, можете привести пример из реального мира?
Вот Вы мне опять доказываете мол на ООП можно замоделировать все. Да, можно конечно, никто же и не спорит :)

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

Но однозначно при любой парадигме придется учить / воспринимать уйму искусственных абстракций, не имеющих аналогов в реальном мире.
Если это ФП, то придется познать функции, карринг, рекурсию и т.п.
Если это ООП — виртуальные методы, интерфейсы, композицию, наследование и т.п.

Мой посыл звучит примерно так: не нужно слепо следовать вере в силу ООП, нужно разумно принимать его сильные и слабые стороны. ООП хоть и работает с объектами, но все равно лишь моделирует наш мир в силу своих возможностей, во многих случаях ФП удобнее. А поэтому ну очень полезно ФП таки знать на том или ином уровне. Чего и Вам желаю.

ЗЫ: чую что Вы мне начнете сейчас доказывать, мол карринга в реальном мире нету, зато есть виртуальные методы… А скорее даже что мол виртуальные методы суть деталь реализации, поэтому забьем на них… Нет! Так никакого конструктивиста не будет, предлагаю вам выбрать один истинно ООПшный ЯП и рассматривать его.
Вот Вы мне опять доказываете мол на ООП можно замоделировать все. Да, можно конечно, никто же и не спорит :)
мы не можем описать (моделировать) реальный мир посредством ООП с высокой точностью
Вы сами себе противоречите.

не нужно слепо следовать вере в силу ООП, нужно разумно принимать его сильные и слабые стороны
С этим вроде никто и не спорит, к чему эти капитанские доводы?

во многих случаях ФП удобнее.
Жаль что нет конкретики. Я в общем-то с этим не спорю, но просто нахожу забавным, что вместо конкретных примеров вы предпочитаете отсылаться к абстрактным «многим случаям».
Сначала делаете дешевые вбросы «какой интерфейс у кота» и «где в реальном мире паттерн Strategy», а потом сливаетесь на капитанском «ООП — не серебряная пуля, во каких-то случаях ФП лучше». Эх, а ведь мог бы годный холивар получиться. Не торт…
Вы сами себе противоречите.
К сожалению я не всегда хорошо вырожаю мысли. А вообще ООП языки полные по Тьюрингу. С этой стороны на них можно создать любую программу-модель. Другой вопрос, что в полученной модели может оказаться, что и кот реализует ICloneable, и яма сама себя копает и т.п.

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

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

Раз уж вы хотите конкретики, то приведите пример «на зверушках» для вышеупомянутых абстракций (strategy, enumerable, cloneable). А заодно укажите на соответствующие «абстракции из реального мира». Ведь ооп лишь повторяет.

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

Эх, а ведь мог бы годный холивар получиться. Не торт…
Слабенько у Вас как-то выходит. В другой ветке вон на личности переходили фразами «Вас заклинило?». А Вы тут прибегаете к мягким «капитанство», «банальные вбросы», «не торт»…
Исходным тезисом (который я опровергаю) было
ооп повторяет абстракции реального мира.
Раз уж вы хотите конкретики, то приведите пример «на зверушках» для вышеупомянутых абстракций (strategy, enumerable, cloneable)

У вас требования неправильные. Зверушки это одна предметная область (реального мира), стратегии другая. И обе моделируются с помощью ООП.

Раз уж вы хотите конкретики, то приведите пример
Вы серьезно? Ваша конкретика заключается в том, что вы решили потребовать ее от меня? «Если вам нужны деньги, то дайте мне 5 рублей»?

приведите пример «на зверушках» для вышеупомянутых абстракций (strategy, enumerable, cloneable). А заодно укажите на соответствующие «абстракции из реального мира». Ведь ооп лишь повторяет.
Я ведь уже отвечал на этот вопрос, но так уж и быть, повторюсь: из утвержения «ООП повторяет абстракции реального мира» не следует «ООП обязано использовать исключительно абстракции реального мира».
Понимаете, если у бизнеса есть требование «пользователи могут покупать товары», это всего лишь означает что у вас есть сущности Пользователь и Товар, и у пользователя есть возможность совершить покупку. Но из этого не следует, что кроме этих двух-трех сущностей нельзя использовать вообще никакие другие абстракции.

Достоинство ООП в том, что оно позволяет выделить один из уровней абстракции, который соответствует реальному миру. Никто (кроме вас, похоже) не требует, чтобы был только один уровень. К слову, раскладывать абстракции на уровни — не самая легкая задача, а иногда и вообще не решаемая (cross cutting concern).

Естественно, что когда вы спуститесь на более низкий уровень, там уже будут другие абстракции — в том числе и ваши любимые strategy/enumerable и т.д. (впрочем неясно зачем вы мешаете паттерны проектирования и интерфейсы в одну кучу).

Просто поймите, что enumerable/cloneable это не абстракции уровня бизнес-логики. Они на более низком уровне. Не на уровне зверушек.
А вы почему-то требуете чтоб вам низкоуровневые абстракции объяснили на примере высокоуровневых. Это просто глупо. Сложные вещи состоят из простых, а не наоборот.
ООП ради того и создавалось, чтоб была возможность разделять уровни абстракций, а вы сейчас жалуетесь на то, что нельзя их смешать в одну кучу.

Т.е. заявляется что ООП использует некие «абстракции из реального мира», а их с свою очередь можно объяснить на примерах со зверушками

Вы подменяете понятия:
— Я употребляю в пищу мясо.
— Ты врешь, я видел как ты ел салат!

Не знаю умышленно вы это делаете или нет, но это дешевая демагогия.
Вы серьезно? Ваша конкретика заключается в том, что вы решили потребовать ее от меня? «Если вам нужны деньги, то дайте мне 5 рублей»?
Т.е. примеров вы привести не можете? Я просил 2 типа примеров, но так уж и быть, упрощу задачу специально для Вас. Приведите, пожалуйста, конкретные примеры абстракций из ФП, для которых нужны формулы и теория множеств в ФП, а вот в ООП либо достаточно лишь зверушек, либо таких абстракций вообще нет.

Я ведь уже отвечал на этот вопрос, но так уж и быть, повторюсь: из утвержения «ООП повторяет абстракции реального мира» не следует «ООП обязано использовать исключительно абстракции реального мира».
А что из этого следует? Что, мол, в ООП и реальном мире есть несколько общих абстракций? А у ФП и реального мира, значит, общих абстракций нету? Или ФП тоже повторяет абстракции реального мира? Поясните пожалуйста.

Вообще вы очень хорошо расписали про абстракции. И что у абстракций есть уровни. И что существует бизнес-логика. И даже причины создания ООП приписали…

У меня вопрос: Вы действительно верите, что вне ООП нету уровней абстракции / выделения уровня бизнес-логики / сложные вещи не состоят из простых / нету способов разделять уровни абстракции / нет возможности выделить один из уровней абстракции, который соответствует реальному миру. Вы действительно так считаете?

Вы подменяете понятия:
это дешевая демагогия
Это уже лучше, мне нравится! Правда фраза про «5 рублей» сильно портит общее впечатление, но это явный прогресс.
Приведите, пожалуйста, конкретные примеры абстракций из ФП, для которых нужны формулы и теория множеств в ФП, а вот в ООП либо достаточно лишь зверушек, либо таких абстракций вообще нет.
Во-первых странно что я должен приводить примеры для утверждений, сделанных не мною. Более того, вы еще и вольным образом пересказываете чужие слова, вставляете отсебятину, а потом радуетесь что ваш пересказ чужого мнения не опровергают. Из чего пытаетесь сделать вывод, что чужое мнение не верно. Браво.

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

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

А что из этого следует? Что, мол, в ООП и реальном мире есть несколько общих абстракций? А у ФП и реального мира, значит, общих абстракций нету? Или ФП тоже повторяет абстракции реального мира? Поясните пожалуйста.
Вы опять придумываете какие-то утверждения, которые другие вынуждены опровергать.
Это означает лишь то, что ООП ближе к естественному мышлению людей. Именно поэтому оно так популярно.

Вы действительно верите, что вне ООП нету уровней абстракции / выделения уровня бизнес-логики / сложные вещи не состоят из простых / нету способов разделять уровни абстракции / нет возможности выделить один из уровней абстракции, который соответствует реальному миру. Вы действительно так считаете?
Нет, не считаю. Опять я вынужден опровергать какие-то глупые утверждения, которые вы пытаетесь приписать мне. Ну прям канонический «не верблюд».

Правда фраза про «5 рублей» сильно портит общее впечатление, но это явный прогресс
А чем именно она подпортила впечатление? Я сказал что у вас слишком расплывчатые утверждения, на что вы ответили «если вы хотите конкретики, то приведите пример». Вам не кажется демагогией, что на мою просьбу о конкретике, вы отреагировали не своими примерами, а потребовали их от меня? Я все еще жду примеров, если что.
Во-первых странно что я должен приводить примеры для утверждений, сделанных не мною…
Так Вы согласны с этими утверждениями или нет?

Во-вторых сама ваша просьба говорит о том, что вы не понимаете о чем говорите. Для высокоуровневых абстракций теория типов не нужна
Наверное я тупой, но не понял что Вы сказали :)

В-третьих, вы упорно продолжаете игнорировать мое пожелание о конкретике (которое я выразил раньше, чем вы)… Приведите пожалуйста хотя бы несколько из этих «многих случаев».
Т.е. вы примеры не хотите привести, но у меня просите. Давайте очень конкретный пример: нужно сделать бота для игры в карточную игру дурак. Как Вы думаете, стоит ли тут использовать ООП или ФП? Может вообще что-то другое?

Или, допустим, построить простую модель поведения планет в звездной системе (сила тяжести и т.п.). Где в каждый момент у планет есть координаты, вектор скорости и нужно отрисовать как они летают по своим орбитам, сталкиваются. Стоит ли тут использовать ООП? Если да, то какие будет объекты?

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

А чем именно она подпортила впечатление
Сложно сказать… Не элегантно как-то. Не тонко. Еще есть куда расти.
Так Вы согласны с этими утверждениями или нет?
В том-то и дело, что с утверждениями copal я во многом согласен, а вот с тем, как вы их переформулировали — нет. Потому что в своей формулировке вы подменяете понятия и додумываете ложные выводы.

Т.е. вы примеры не хотите привести, но у меня просите.
Перечитайте тред. Вообще-то именно я вас упрекнул в отсутствии конкретики, на что вы отреагировали «если хотите конкретики, то приведите пример...». Немного неадекватно, вам не кажется?

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

стоит ли тут использовать ООП или ФП
Вопрос «стоит ли» некорректен. Что «стоит» делать обычно зависит не только от задачи, а от доступных ресурсов. Если вы всю жизнь писали на Lisp, вам не «стоит» бросать все и решать эту задачу на каком-нибудь Java.

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

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

Получается, что другие методологии этого не позволяют?
Вот как, объясните мне как, из фразы «ООП хорошо позволяет сделать Х» вы делаете вывод «в ФП невозможно Х»? Это абсолютно неэквивалентные утверждения, почему вы постоянно вынуждаете собеседника доказывать, что он не верблюд?
В вас просто зашкаливает какой-то неадекватный максимализм.
Вот как, объясните мне как, из фразы «ООП хорошо позволяет сделать Х» вы делаете вывод «в ФП невозможно Х»
Вы искажаете свои же фразы. Первоначально вы писали «достоинство ООП в том, что у него есть X». Все хорошо, но ведь X есть у всех. Так себе достоинство, если честно.

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

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

Какие классы/объекты Вы вы бы выделили? Какие сообщения они будут посылать друг другу?
Как-то мало информации вы выдали для того чтоб что-то проектировать. ТЗ когда-нибудь писали? «Написать бота» — это не ТЗ.

Вы, кстати, до сих пор не удосужились привести примеры упомянутых вами «многих случаев» где ФП удобнее для проектирования реального мира. От меня уже проектировать что-то требуете, а сами до сих пор не соизволили свои же слова подтвердить. Я все еще жду конкретных примеров, хотя бы парочку выдайте.
Достоинство ООП в том, что оно позволяет сравнительно легко выделить один из уровней абстракции, который соответствует реальному миру.
А ФП, получается, позволят, но с трудом? «Сравнительно легко» с чем?

В качестве подтверждения могу вам предложить тотальное доминирование ООП в промышленной разработке
Есть такое дело. Нынче ООП доминирует.

Вы, кстати, до сих пор не удосужились привести примеры упомянутых вами «многих случаев» где ФП удобнее для проектирования реального мира.
Примеры я уже приводил, максимально конкретные. В них использование ФП даст, с моей точки зрения, более читаемый, сопровождаемый и тестируемый код, нежели ООП.

Главная и самая банальная причина — ООП там не нужен. Тут сложно выделить сущности для ООП. Сделайте это, если я не прав (применительно к карточной игре). ООП в этих задачах не пришей кобыле хвост.

С ФП же все лучше, есть реальный профит по сравнению со структурным программированием: состояние всей системы (колода и карты в руках) в одной большой структуре данных (легко отлаживать программу); вся логика декомпозирована в набор чистых функций. А чистые функции легче писать, тестировать, читать.
Я привел ссылку на «Object Oriented Programming» vs «Fucntional Programming» (второй график на вашем комментарии). Вы ответили ссылкой на «Объектно Ориентированное Программирование» vs «Функциональное Программирование» (русский язык, первый график).

И где же тут подмена понятий? Де-факто мировым языком IT является английский.
Переключите свой аккаунт на англ, не позорьтесь.
Ну… Ваш график подтверждает ваши и мои слова — ООП популярнее, однако его популярность постепенно снижается.
Давайте очень конкретный пример: нужно сделать бота для игры в карточную игру дурак.
Тут сложно выделить сущности для ООП.

Ну вот вам дурак. Есть вполне понятные сущности типа "Игрок", "Колода", "Карта", ну и сам движок. Движок занимает 300 строк, отрисовка 200, описание сущностей 140.


Переопределив методы выбора карт в разных реализациях класса Player, можно передавать в движок игроков, которые будут играть по-разному. Методы разделены по объектам, к которым относятся. Это удобнее воспринимать, чем если бы они все были в движке, хотя большинство все же там.
Изменяемого состояния не то чтобы много, но оно есть, и с ним удобнее.


Приведите аналогичный пример реализации на ФП, будем сравнивать)

Спасибо! На досуге попробую это дело переписать на Clojure, посмотрим что получится, сравним подходы :)
Вероятно оформлю это дело в виде статейки.
мы не можем описать (моделировать) реальный мир посредством ООП с высокой точностью

Это потому что у ООП нет некоторых возможностей описания терминов.


Например, имеется ли в реальном мире объект, умеющий в ICloneable? Чтобы так взял и скопировал сам себя?

Это объект не из живой природы, если вы об этом. Это технический объект (объекты) из предметной области "програмирование". Программисты выделили в окружающим их мире объекты, обладающие схожим поведением, и дали им название. Все как и с любыми другими терминами.
Реальный мир — это не только живая природа, это окружающий мир в целом.
Хотя на некотором уровне абстракции таким объектом можно назвать делящуюся клетку.


Для наглядности приведу известную «проблему»: лопата копает яму или яма копается лопатой?
Поэтому иногда в наших программах лопата копает яму, в другой раз яма копается лопатой, в третий раз у нас есть рабочий который копает яму и пользует лопату…

А почему это проблема? Если у нас лопата сама копает яму, то это неправильное моделирование. Можно назвать его неточным, но тем не менее мы просто не учитываем часть реальных (выделямых нами в реальном процессе) объектов — рабочего, который держит лопату.
Если в рамках этой модели у вас не возникает противоречий, значит да, она достаточная для задачи. Но надо понимать, что мы отказались от части модели, и при изменении задачи это может привести к проблемам.

Если считать CLOS и вообще говоря мультиметоды, ООП, то там не будет однонаправленности, динамическая диспетчерезация будет по M аргументам.

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

Даже если сказать, что остаётся вопрос порядка аргументов,
dig(shovel, tool) или dig(shovel, hole), можно найти ЯП с поддержкой именованных аргументов: dig(tool=shovel, hole=hole).

Это я к чему: ограничения конкретных ЯП очень слабо отвечают на вопрос ограничений или проблем ООП.
Спасибо за комментарий. С одной стороны я согласен, что мультиметоды решают проблему «ямы и лопаты». С другой — а это действительно ООП?
Например в Clojure тоже есть мультиметоды. Clojure — ООП язык?

Все же в ООП предполагается «посылка сообщений от одного объекта к другому», которая в наших реалиях выродилась в «вызов метода». Но ведь посылка сообщения по определению ассиметричная.
С другой — а это действительно ООП?
Например в Clojure тоже есть мультиметоды. Clojure — ООП язык?

Вы, похоже, не понимаете разницы между ООП и ООП-языками.
Представьте себе, объектно-ориентированное программирование возможно и на функциональных языках, и на процедурных.
Вы, похоже, не понимаете разницы между ООП и ООП-языками.
Хорошо, я поставлю вопрос несколько по-иному. А также перенаправлю его лично Вам, раз уж вы разбираетесь в ООП на Ф языках.

Если программист использует мультиметоды в Clojure — использует ли он в этот момент ООП?
В общем случае — конечно же нет.
Мне непонятно откуда вообще мог взяться этот вопрос. Вы увидели полиморфизм и вам показалось что запахло ООП?
Исходно было предположение
Если считать CLOS и вообще говоря мультиметоды, ООП ...
Так вот на мой взгляд мультиметоды некорректно считать ООП.
С чем Вы только что, кстати, согласились :)
Так вот на мой взгляд мультиметоды некорректно считать ООП.

Смешной вы. Задам очевидный вопрос: а CLOS+мультиметоды вы считаете ООП?

Исходно ведь было ваше предположение, что в ООП обязательна однонаправленность (странный термин и проблема, ну да ладно). На что вам привели пример: CLOS+мультиметоды. Вы зачем-то стали нести какой-то бред о том, что мультиметоды — это не означает ООП.

Ну да, не означает. Вот только как это отменяет то, что вам привели пример ООП без однонаправленности, опровергающий ваше утверждение?

Опять же типичная демагогия. В одном контексте делаем два утверждения, одно спорное, второе очевидно истинное. Чтоб потом была возможность сказать «вы же сами со мной согласились!». Я согласился с очевидным утверждением (мультиметоды не означают ООП), а не со спорным (ООП по определению однонаправленно)
Задам очевидный вопрос: а CLOS+мультиметоды вы считаете ООП?
Нет, я не считаю CLOS классическим ООП (про которое тут недавно упомянули). А это разве было не ясно по моим высказываниям?
Ага, понятно. ООП плохое потому что оно по определению однонаправленное, а если мне покажут контрпример, я просто скажу что это «не настоящее ООП» (ну или не «классическое»).
Слушайте, да вы просто ходящий сборник уловок демагога!
Слушайте, да вы просто ходящий сборник уловок демагога!
Что-то вместо разговора по делу Вы переходите на личности.

Давайте по теме (ООП и CLOS). Является ли с вашей точки зрения инкапсуляция (упаковка аттрибутов и методов в один контейнер/объект) одной из необходимых характеристик ООП?
Я вижу вы таки осилили почитать про CLOS и теперь надеетесь подловить меня на том, что в ней нет википедийной инкапсуляции. Рекомендую меньше читать русскую Википедию.

Инкапсуляция — это не «упаковка в контейнер», а связь между функцией и данными, с которыми функция оперирует. В такой формулировке инкапсуляция является необходимой характеристикой ООП, и в такой формулировке она есть в CLOS: именно благодаря этой связи рантайм понимает какой именно метод нужно вызвать.
Как я погляжу, уже начали придумывать свои формулировки?

А вот допустим у меня в ФП программе есть тип «список чисел». И для такого типа определена функция sum (сумма элементов). Между типом и функцией есть связь? Есть ли тут инкапсуляция?
Как я погляжу, уже начали придумывать свои формулировки?
Неправильно глядите. Вы объясняете инкапсуляцию через «что», а я — через «зачем». К сожалению ООП в 90% случаев преподносится именно через «что». В итоге имеем карго-культ — нелепо повторяем какие-то вещи, без понимания сути.

Попробуйте вместо русской википедии почитать хотя бы английскую. Там про инкапсуляцию пишут не packing, а bundling. Разницу улавливаете?

Если нет, то я вам подскажу: упаковывают (pack) для сжатия или транспортировки. Например вино в ящики. Или файлы в архив/сеть.
А «связывают» (bundle) — по смыслу. Например вино и штопор. Или структуру «кошка» и метод «мяукать».

Какой смысл вы вкладывали в свою программу — знаете только вы. Для меня вы выдали слишком мало информации, чтобы ответить на ваш вопрос.
Если нет, то я вам подскажу: упаковывают (pack) для сжатия или транспортировки. Например вино в ящики. Или файлы в архив/сеть.
А «связывают» (bundle) — по смыслу. Например вино и штопор. Или структуру «кошка» и метод «мяукать».
Слушайте, ну это уже перебор. Почитайте словари, что-ли. «Связывают вино и штопор» если только в магазине, ленточкой красной, и общий ценник вешают, чтобы продать «одним бандлом» :)

Я свое мнение уже высказал — CLOS я не считаю ООП. А тем более мультиметоды. Можете с этим мнением не не соглашаться, дело ваше. Но пожалуйста, не пытайтесь его опровергать путем придумывания своих формулировок и переводов.
Почитайте словари, что-ли.

«A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data»

Открываем словарь:
bundling
связывание, складывание; пакетирование; сматывание
соединение; сочетание
группирование;

Упаковывания не нашел.

CLOS я не считаю ООП
Забавно. И эти люди запрещают мне ковыряться говорят мне не придумывать своих формулировок.
Открываем словарь:
bundling
связывание, складывание; пакетирование; сматывание
соединение; сочетание
группирование;

Упаковывания не нашел.
Ну, все правильно. Только вы еще в толкование загляните, по вашей же ссылке, это не сложно.
общ. (собирание вещей (грузов, товаров) в связки, узлы или пакеты, а также сматывание верёвок) марк. (объединение нескольких товаров в набор
Смысл улавливаете?

Даже больше, по вашей же (!) ссылке есть
пример со словом 'упаковать'
(You can bundle legacy applications into a so-called ZAP file that is little more than a batch file for launching the application's setup program.)

(Устаревшее приложение можно упаковать в файл ZAP, который представляет собой пакетный файл, запускающий программу установки приложения.)



Что-то пошел полный оффтоп. Думаю эту ветку стоит закрывать, слишком она уныла.
Какие интерфейсы реализует Кот?

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


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


Какие сообщения он может посылать, принимать?

Такие же, как и любые другие существа — голосовые, визуальные, тактильные.


Кот и кошка — это объекты разных классов или одного?

Лучше сказать, это объекты разных типов. Типы ближе к логическому понятию "термин". Классы из C++ или Java ближе к структурам данных. От этого происходят все несоответствия, когда мы пытаемся искать аналоги.
Если не вдаваться в детали реализации, то структура у этих объектов одна, а отличаются они по значению параметра "gender" — "male/female". А если вдаваться, то gender это просто более сложный подобъект, влияющий на наблюдаемые параметры и поведение. Вот и инкапсуляция появилась. Только она не у кошек, а у тех, кто с ними взаимодействует. Они выделяют у кота и кошки различия, детали реализации которых их не волнуют.


Когда кошка рожает котят… это наследование?

Для использования объектов необязательно использовать наследование. Это создание объекта, у которого после создания появляется свое поведение. Создается объект того же класса, структура которого задается ДНК, а конкретные характеристики появляются в процессе функционирования.



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

Рискну сослаться на свой комментарий в параллельной ветке

Добавлю, что ведь никто не собирается отказываться от ООП — а зачем?
Но ведь и свято верить в его универсальность и «соответствие реальному миру» не стоит. Статья кстати призывает изучить ФП, а уж что применять при решении конкретных проблем — это остается выбором программиста. Если, конечно, у того есть голова на плечах.

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

Потому что оно универсально и соответствует нашему восприятию мира.
А вы, простите, на какой вопрос ответили?

функции на низком уровне сами превращаются в объекты с состоянием.
И в какой объект превращается sin?

Это я неправильно совместил "а зачем?" и "свято верить в его универсальность не стоит") Вы говорите, что оно не универсально, а я считаю, что универсально. Потому что мы выделяем объекты и даем им названия. И даже слово "действие" это существительное. Хотя главное не сами объекты, а их типы.


И в какой объект превращается sin?

В частный случай замыкания без состояния. И даже если считать это притянутым за уши, то в ФП функция это переменная типа "функция", то есть объект, и у нее есть свойства — например, начальная точка, тело, сигнатура.

функции на низком уровне сами превращаются в объекты с состоянием.
Ну ООП языки суть полные по Тьюрингу… Так что они в этом смысле, разумеется, универсальны.

Ну так и ФП тоже универсально :)
В природе мы выделяем процессы и даем им названия. И даже слово «действовать» это глагол. Хотя главное не сами процессы, а их типы :)

В частный случай замыкания без состояния. И даже если считать это притянутым за уши
Это слишком притянуто за уши :) А вообще во многих ООП языках каждый объект это переменная типа «указатель», указывает на структуру, а у нее есть поля — например, указатель на vmt, информация о типе…
И даже слово «действовать» это глагол. Хотя главное не сами процессы, а их типы

Это да, немного подловили) На словах получается похоже. Но мы не говорим просто типы, мы говорим типы чего-то. Какого-то существительного. На одних глаголах нельзя построить модель, они должны действовать с чем-то.


А вообще во многих ООП языках каждый объект это переменная типа «указатель», указывает на структуру, а у нее есть поля

Правильно, это тоже объекты, более низкого уровня. Они нужны для описания модели.

Объекты типа "функция" мало того что есть во многих языках, так еще и вполне естественны. Потому что у них есть свойства, вполне очевидные — и вам их сразу назвали. И более того, вы можете этими свойствами манипулировать, создавая другие объъекты из этого — например, путем частичного применения (для sin это вырожденный случай, но в общем случае — нет).


И где вы тут видите "слишком"? Функция вполне естественным образом отображается на объект. Другое дело, что это не всегда нужно.

Простите что встреваю, но ООП это не про абстракции реального мира…
Алан Кей (создатель ООП и языка Smalltalk) вкладывал в ООП немного другой смысл, и он не про «объекты» вообще. Позволю себе несколько цитат:
ООП для меня это сообщения, локальное удержание и защита, скрытие состояния и позднее связывание всего. Это можно сделать в Smalltalk и в LISP.

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

Большая идея это «сообщения»

Большинство людей, получающих дипломы в CS, не понимают всей важности Lisp. Lisp это самая важная идея в computer science.

Алан считает LISP лучшим языком программирования когда-либо созданным.
Важность LISP для CS трудно переоценить.
Классический курс MIT, переведенный и используемый впоследствии во всем мире,
SICP (Структура и интерпретация компьютерных программ), использует Scheme — диалект LISP.
Безусловно все это, не значит что все бросают ООП и бегут изучать лисп. Но это говорит о важности языка и его диалектов, их широких и мощных возможностей. И современный промышленный диалект такого языка, это безусловно здорово. К таким относится Clojure.
От себя добавлю что все разговоры об ООП и языках, это субъективные взгляды. Кому-то кажется сложным, кому-то наоборот, синтаксис и тд. Это субъективное восприятие каждого.
Опишу свое. Я увлекаюсь Сlojure уже чуть больше года. И просто поражен простотой. Хотя поначалу все казалось бредом и наполненным сложными концепциями. Просто наступил момент когда надо было себя пересилить, и не бросить, из-за совершенно надуманной сложности. Очень давно хочется написать небольшую практическую статью, на примере простого веб-приложения на веб-сокетах на Clojure, если это будет интересно. Уверяю многие должны удивиться простоте того как это выглядит, читается, и пишется. И главное отлично работает. И никаких теорий множеств и того о чем вы упомянули. Спасибо.
ООП это не про абстракции реального мира…
Вообще-то любое программирование как раз про абстракции реального мира.

Перестаньте рассматривать абстракцию как часть догмы «абстракция, наследование, инкапсуляция, полиморфизм».
Абстракция — это не то, что Alan Kay засунул в ООП, а то, ради чего он его создал.

А статью пишите конечно. Чем больше популяризации ФП на реальных примерах, тем лучше.
Говорят что синтаксис Лиспа и родственных ему языков ближе всего к синтаксическому дереву как таковому. Это правда?
То что ФП важно по-моему ни у кого уже сомнений не вызывает:)
Код на лиспе это и есть практически готовое синтаксическое дерево. Это достигается как раз за счёт скобок. Новая пара скобок — новое поддерево.
Закон Мура говорил нам что скорость компьютеров будет удваиваться каждые 18 месяцев.

Никогда он такого не говорил. Закон Мура вообще про другое — он про число транзисторов.

Для бедных

Как-то однажды знаменитый учитель Кх Ан вышел на прогулку с учеником Антоном. Надеясь разговорить учителя, Антон спросил: «Учитель, слыхал я, что объекты — очень хорошая штука — правда ли это?» Кх Ан посмотрел на ученика с жалостью в глазах и ответил: «Глупый ученик! Объекты — всего лишь замыкания для бедных.»

Пристыженный Антон простился с учителем и вернулся в свою комнату, горя желанием как можно скорее изучить замыкания. Он внимательно прочитал все статьи из серии «Lambda: The Ultimate», и родственные им статьи, и написал небольшой интерпретатор Scheme с объектно-ориентированной системой, основанной на замыканиях. Он многому научился, и с нетерпением ждал случая сообщить учителю о своих успехах.

Во время следующей прогулки с Кх Аном, Антон, пытаясь произвести хорошее впечатление, сказал: «Учитель, я прилежно изучил этот вопрос, и понимаю теперь, что объекты — воистину замыкания для бедных.» Кх Ан в ответ ударил Антона палкой и воскликнул: «Когда же ты чему-то научишься? Замыкания — это объекты для бедных!» В эту секунду Антон обрел просветление.

Ограничение скоростью света было достигнуто. Сигналы не могли распространяться по поверхности чипа достаточно быстро для обеспечения больших скоростей

Это была шутка про причину уменьшения роста производительности?

Что ж, ФП проще писать, проще читать, проще тестировать и проще понимать. Представляю как некоторые из вас сейчас размахивают руками и кричат на экран. Вы попробовали ФП и нашли его каким угодно, но не простым. Все эти map и reduce, и вся эта рекурсия — особенно хвостовая рекурсия — какие угодно, но не простые. Конечно. Я понял. Но это лишь проблема знакомства. Как только вы стали знакомы с этими концепциями — и развитие этого знакомства займет не так много времени — программирование станет намного проще.
Тем, кто считает ФЯП сложными, или тем, кто считает, что может освоить в общих чертах любой ЯП за несколько дней, нужно посмотреть какой-нибудь Isabelle HOL. Поначалу воспринимаешь его как обычный ФЯП (с алгебраическими типами данных, рекурсивными функциями, pattern-matching и т.п.) + немного примочек для доказательства теорем. Всякие индуктивные предикаты или множества кажутся какой-то непонятно зачем нужной шнягой, без которой вполне можно обойтись. Потом в мозгу что-то переключается и понимаешь, что они гораздо удобней и лучше функций, и начинаешь всё описывать преимущественно через предикаты. Они напоминают логические утверждения в Prolog или Mercury, только круче. Потом начинаешь фигачить свой синтаксис со всякими стрелочками, непонятными символами, которые очень любят математики, активно используешь греческие буквы в коде. Спустя год использования Isabelle HOL понимаешь, что изучил наверное не больше 10% языка. А ещё там есть кнопка «кувалда», когда не знаешь как доказать какую-нибудь теорему, жмешь эту кнопку и всё само доказывается. Поначалу очень помогает. Представляете в обычных ЯП была бы такая кнопка, не знаешь как реализовать алгоритм, нажал кнопку, он сам как-то реализовался, пусть не очень оптимально, но потом можно зарефакторить.
Функциональные языки- это все очень здорово. Даже больше. Каждый, кто более-менее серьезно и регулярно пишет программы приходит к тому, что их таки нужно учить. И это действительно приносит свои плоды.

Но все безоблачно только в самых основах. Простые примеры вроде бы понятны и все отлично работает. Пока ты на мелководьи водичка теплая, светит солнышко и вокруг тебя плавают маленькие рыбки. Но вот когда начинаешь погружаться чуть глубже, начинаешь видеть глубоководных чудовищ. И тут уже не до смеха.

Я хорошо запомнил статью, в которой автор писал на Haskell разбор файлов, которые ему отдает ATC. И вроде бы Haskell славится скоростью, но его программа колбасилась с файлами по пол-часа. Комментарии было читать очень интересно и его программа в результате стала гораздо лучше, но я не сказал-бы что все они мне дались легко. Для понимания многих из них пришлось хорошо покурить доки. Но даже несмотря на все старания программа не стала молниеносной.

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

И после всего этого как-то не очень верится в простоту функциональных языков.

Ну и учить Lisp и его производные советовать я бы лично точно не стал. Все-таки его синтаксис просто безумие чистой воды. И то, что гуру Lisp советуют в случаях, когда вы не можете разобраться со скобками- перепишите или поверьте написанному, говорит о очень многом. Тот-же Haskell выглядит куда более читаемым, а Scala так вообще выглядит привычнее некуда и при этом совместима с Java.

В общем не все так безоблачно в функциональном королевстве.
Зря вы так про синтаксис Lisp. Как тут выше заметили, за счет «безумия» появляется возможность работать на уровне AST, в том числе расширять язык. Т.е. кривая обучения очень высокая, это да. Хотя, при изучении программирования с 0, думаю, разницы бы особой не было. С другой стороны «дикий» синтаксис дает нам богатые возможности метапрограммирования и потрясающую гибкость языка (и конечно возможность стрельнуть в ногу себе и своему коллеге разумеется). Очень многие вещи в языке на самом деле реализованы на уровне рантайма, например and. Да что там, даже создание локальных переменных реализовано через макрос let

гуру Lisp советуют в случаях, когда вы не можете разобраться со скобками- перепишите или поверьте написанному
Так себе гуру, если чЭсна :)

Тот-же Haskell выглядит куда более читаемым, а Scala так вообще выглядит привычнее некуда и при этом совместима с Java.
Вот не надо, не надо :)
Haskell вообще некорректно сравнивать. Синтаксис у него, конечно, попривычнее. Хотя тут можно поспорить, что понятнее (f (g a b)) или f $ g a b. Зато семантика…

Со Scala все тоже сложно. Многие, в том числе и я, считают язык слишком переусложненным. Интероп с Java кстати у Clojure проще нежели у Scala: как минимум не надо возится с преобразованием коллекций и прочей бюрократией, нет проблемы дженериков (нет дженериков — нет проблем) и т.п.
Хотя, при изучении программирования с 0, думаю, разницы бы особой не было.

В этом вопросе я готов спорить до хрипоты опираясь на свой опыт. Я подучиваю свою дочку программированию. И не давать ей выбора- не мой путь. Поэтому я ей рассказал с самого начала общие подходы и предложил начать именно с функционального программирования. Просто что-бы понять что это хотя бы в самых азах. Скажу сразу, что идея ФП ей понравилась. Мы взяли Lisp и начали писать простенькие программки. И очень быстро дочка сказала, что Lisp ей не нравится. Не идеями, а именно синтаксисом. И это мы говорим о ребенке с великолепной памятью, развитым пространственным мышлением и отличными математическими способностями.

А вот с Java и после с Python у нее вообще не было никаких проблем.

и конечно возможность стрельнуть в ногу себе и своему коллеге разумеется

Вот именно это меня и смущает. Я сторонник кода, который можно разобрать даже с жесткого бодуна. Просто в свое время учился программировать у людей, которые всю жизнь делали системы управления для критически важных систем. В основном для космоса. И когда то, что ты писал уезжает на АЭС выстрел в ногу выглядит несколько с другого ракурса.

Так себе гуру, если чЭсна :)

Кто это был я сейчас не вспомню, но кто-то с мировой известностью из мира Lisp. Так что какие есть ;)

Haskell вообще некорректно сравнивать.

А почему не корректно? Хотелось бы узнать ваше мнение в общих чертах.

Со Scala все тоже сложно. Многие, в том числе и я, считают язык слишком переусложненным. Интероп с Java кстати у Clojure проще нежели у Scala: как минимум не надо возится с преобразованием коллекций и прочей бюрократией, нет проблемы дженериков (нет дженериков — нет проблем) и т.п.

Что-то получили, что-то потеряли. Но тут я готов терпеть Scala. Очень уж мне не нравится синтаксис Lisp-a. Я долго не мог начать учить Python из-за его отступов, но в конце-концов я с собой справился и рад этому. Но вот со скобочками я ничего не могу с собой поделать.
В этом вопросе я готов спорить до хрипоты опираясь на свой опыт.
Ваш опыт описывает лишь единичный случай, чего маловато для доказательства (привет, матстатистика). Хотя и у меня никакой статистики нету, возможно Вы и правы.

и конечно возможность стрельнуть в ногу себе и своему коллеге разумеется
Тут кстати не все так плохо. Как по мне, так даже поприличнее, нежели у многих мейнстримовых языков. Хотя тут, возможно, заслуга коммьюнити, а не самого языка.

А почему не корректно? Хотелось бы узнать ваше мнение в общих чертах.
Я несколько неверно выразился. Скорее нужно сказать «не имеет смысла». Ведь сложность Haskell далеко не в синтаксисе…
Да и синтаксис там, к слову, сложный — можно навводить новых операторов с кастомным приоритетом. А потом городить всякие (*) <$> (+3) <*> (*2) $ 2. А вот в Lisp вообще нету операторов и их приоритета ;)

Очень уж мне не нравится синтаксис Lisp-a. Я долго не мог начать учить Python из-за его отступов, но в конце-концов я с собой справился и рад этому. Но вот со скобочками я ничего не могу с собой поделать.
Ну вот Вы не можете начать учить Lisp, как не могли начать учить Python. Наверняка думали «ну с отступами я ничего не могу с собой поделать». Согласен, привыкнуть к S-выражениям куда сложнее, чем к отступам. Но это все равно дело наживное.

Кстати, скобочек в Clojure зачастую меньше выходит, нежели в Java. Сравните и посчитайте скобочки сами:
if (obj.isReady()) {
    processStuff(obj.getA(), obj.getB());
} else {
    doNothing();
}
vs
(if (is-ready obj) 
  (process-stuff (get-a obj) (get-b obj))
  (do-nothing)) 

Ваш опыт описывает лишь единичный случай, чего маловато для доказательства (привет, матстатистика). Хотя и у меня никакой статистики нету, возможно Вы и правы.

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

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

От выстрела в ногу не защищен вообще никто. Я недавно воспроизвел это на Python. Хотя казалось бы он делает все, что бы мы не морочились.

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

Я несколько неверно выразился. Скорее нужно сказать «не имеет смысла». Ведь сложность Haskell далеко не в синтаксисе…
Да и синтаксис там, к слову, сложный — можно навводить новых операторов с кастомным приоритетом. А потом городить всякие (*) <$> (+3) <*> (*2) $ 2. А вот в Lisp вообще нету операторов и их приоритета ;)


Как по мне смысл может быть, а может и не быть, в зависимости от целей. Скажем если ваша цель писать на Lisp в определенном проекте учить Haskell как-то вообще бессмысленно. А вот если вы пишете на Java, но хотите понимать что происходит в нововведениях, то языки можно и посравнивать что бы выбрать наиболее подходящий именно вам. И выбранный язык не обязательно будет самым быстрым или самым понятным. Ведь выбор порой не всегда рациональный.

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

Кстати, скобочек в Clojure зачастую меньше выходит, нежели в Java.

Вопрос не в том, что их много. Вопрос в том, как они используются. В Java скобки разные для блока и для функции. Конечно бывают случаи когда смотришь на вызов функции и не можешь понять ")))))" или "))))))" правильно. Но все эти скобки на одной строке, а не в пределах страницы. И если вам действительно не нравятся скобки в куске на Java вы можете от них легко избавится использую поля а не гетеры. Или переписать вот так:
obj.isReady() ? ProcessStaff(obj.getA(), obj.getB()) : doNothing();

Тогда скобок будет меньше ;) Но я не очень люблю эту конструкцию потому, что она снижает читаемость.
бывают случаи когда смотришь на вызов функции и не можешь понять ")))))" или "))))))" правильно
Вот тут я согласен :) Есть такая проблема. Правда есть несколько смягчающих факторов:
— в Clojure скобочек чуть поменьше, чем в CL;
— активно используется несколько видов скобочек (), [], {};
— хороший редактор очень помогает; в частности радужная подсветка скобочек (за качество пакетов ничего не скажу, ибо сам пользую Emacs);

Но все эти скобки на одной строке, а не в пределах страницы.
Отступы. Все решают отступы и правильные редакторы / IDE.

Вообще предлагаю наглядно сравнить читаемость. Под рукой есть вариант кода на Python, и тотже код на Hy (эдакий Clojure для Python):
Сравнение кода на Py и Hy
image
Я любитель Clojure и согласен с выводами статьи, но вообще она так себе.

Теперь, чтобы превратить ее в функцию на Lisp, просто переносим первую скобку влево: (f x).
Теперь вы знаете 95% Lisp, и знаете 99% Clojure.
Сразу чувствуется насколько автор глубоко знает и Lisp, и тем более Clojure.

Так же в Clojure CAR, CDR и CADR заменены на first, rest и second.
Слишком поверхностно и натянуто.

Слышу как вы говорите «Но подожди!», «ФП и ООП взаимно несовместимы!». Кто вам такое сказал? Это чушь!
Это чушь! В смысле чушь что это чушь… В смысле… Ай…

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

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

На уровне JVM производимый байт-код будет идентичным.
Чушь.

Следующий код (1 2 3) представляет список из трех целых чисел. Если первый элемент оказался функцией, как в (f 2 3), тогда это становится вызовом функции.
Строго говоря (1 2 3) это тоже попытка вызвать функцию «1» (что естественно закончится ошибкой выполнения). Список же записывается как '(1 2 3), что суть синтаксический сахар для (quote (1 2 3))
ФП про локализацию состояния системы, разделение данных и алгоритмов по разным углам ринга.
ООП же про размазывание состояния по системе и объединение данных и алгоритмов.

Кажется, это действительно дельное объяснение сути различия ООП и ФП

Слышу как вы говорите «Но подожди!», «ФП и ООП взаимно несовместимы!». Кто вам такое сказал? Это чушь!

Это чушь! В смысле чушь что это чушь… В смысле… Ай…

Но не совсем понимаю, почему это различие делает их взаимно несовместимыми?

Ну, т.е. понятно, что чистая функция рассчитывает на неизменяемые входящие параметры, а «ящичек» вроде как не такой (он же может менять своё состояние), но что, если перед тем, как перекинуть этот «ящичек» в функцию, его предварительно заморозить? Или даже сериализовать в какую-нибудь неизменяемую структуру данных.
А уж использовать чистые функции внутри объектов так вообще ничего не мешает, если передавать в них неизменяемые данные…

но что, если перед тем, как перекинуть этот «ящичек» в функцию, его предварительно заморозить
Можно и просто передать объект, договорившись, что «никто его внутри функции не будет мутировать». Так работают все нестрогие ФП языки (в том числе Clojure).

А уж использовать чистые функции внутри объектов так вообще ничего не мешает, если передавать в них неизменяемые данные…
Именно так! Вполне можно реализовать некий алгоритм при помощи ФП и использвать его из ООП программы. Или наобоорт, можно реализовать императивный алгоритм и всунуть его в ФП код. Т.е. система получается слоистой, как если смешать несколько жидкостей с разной плотностью (вода, масло, керосин и т.п.). Точно также теоретически ничего не мешает одному ЯП поддерживать две парадигмы одновременно. А уже какую использовать решает программист… Можно даже использовать обе одновременно, правда вместо прозрачных и красивых слоев жидкости в банке получится мутная взвесь…
Можно даже использовать обе одновременно, правда вместо прозрачных и красивых слоев жидкости в банке получится мутная взвесь…

Вот непонятно, откуда такой вывод у Вас напрашивается… Мутная взвесь она может получиться и при использовании только одной парадигмы, а может (как мне кажется) и не случиться при использовании нескольких

Это была аллегория :)
Если налить в бутылку две несмешивающиеся жидкости (скажем, растительное масло и воду) и хорошенько-хорошенько так взболтать, то получим мутную эмульсию. Так и с программированием — можно попытаться смешать несмешиваемое, но результат может не впечатлить в плане своей прозрачности.

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

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

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

Вот, например, возьмём метод какого-то объекта (ООП), внутри которого фильтруется (чистой функцией filter, господи, да это же ФП!) некий набор данных ну и потом записывается куда-нибудь в поля объекта. И как так выходит, что это — «мутная взвесь»?

Или Вы всё-таки имели в ввиду что-то другое, говоря, что ФП и ООП лучше не смешивать?
Возможно, этот вопрос вообще из-за неправильных интерпретаций?
Вот кстати да. Многие вкладывают в ООП и ФП примерно такой смысл: я в программе использую объекты — это ООП; использую map/filter — это ФП. При таком подходе, конечно, можно сочетать все со всем.

На мой взгляд это не совсем верно, ООП и ФП суть не просто техники «как отфильтровать массив», а парадигмы, идеологии о том, как же стоит воспринимать и организовать сам процесс вычисления.

Поэтому
Или Вы всё-таки имели в ввиду что-то другое, говоря, что ФП и ООП лучше не смешивать?
я имею в виду, что нельзя одновременно руководствоваться двумя идеологиями, конфликтующими в некоторых своих аспектах.
НЛО прилетело и опубликовало эту надпись здесь
В конце 80-х учился на мехмате МГУ. Помню лекции по программированию, лектор невозмутимо рассказывает про «исполнитель — шагающий человечек», а в аудитории (большая аудитория на целый поток) стоит дикий вой, летают бумажные самолётики, математики протестуют против изнасилования разума. С тех пор мне смешно на ООП.
А то ещё был функциональный язык GARF, из которого помню команду «подставить Ю вместо Я в вещь Щ». Давно это было.
ru-lambda.livejournal.com/148881.html
ФП делает параллелизм намного безопаснее. Если вы создаете систему со множеством потоков, или процессов, тогда использование ФП сильно уменьшит количество проблем с состояниями гонки и параллельными обновлениями, которые вы могли бы иметь.

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

У clojure есть один фатальный недостаток по сравнению с другими ФП языками — слабая типизация. Имхо, мощная система типов обязательна для ФП языков, когда назначение чистой функции можно описать через ее сигнатуру (типы параметров и возвращаемого значения).

Вы часом не путаете слабую типизацию и динамическую? Все лиспы строго типизированные.
А как Вы относитесь, например, к Erlang?
Кстати erlang как уверяют больше других заточен на параллельность. Но «ожидание товарняка» и тут затягивается. Мне нравится Erlang.

В Clojure сильная динамическая типизация, и в помощь даны metadata и spec

Цитата: «Когда вы кладете элемент на вершину стека в ФП-языке, вы создаете новый стек, а не меняете старый. Это означает что программисту нужно жонглировать меньшим количеством мячей одновременно в воздухе.»

Так тут получается что не меньше а больше. Непонятно.
Хм, OOP vs. FP, какая свежая тема… Ещё подкину — линукс vs. винда, vim vs. emacs, pascal vs. c, табы vs. пробелы…
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории