Comments 71
some_array.map(&λ1).filter(λ2).reduce(&λ3)
Эти методы противоречат классическому ООП: они не курочат receiver, но возвращают новый объект.
Никакому классическому ООП эти методы не противоречат.
В стандартной библиотеке Smalltalk прекрасно существуют методы collect: и select:
А уж более классического ООП, чем Smalltalk, придумать сложно
Вставил дисклеймер специально для эрудированных зануд: я в курсе, что называл ООП Алан Кай, но выше использую термин в том извращенном значении, в котором он прижился в современном мире, спасибо Гослингу.
У Вас же огромный опыт в различных парадигмах, давайте вместе не будем называть собаку кошкой, и потом удивляться, что она лает будем настаивать на правильной терминологии. Занудность в этой области - есть гуд!
«Я пишу не для славистов, я пишу для нормальных людей» — как якобы сказал однажды на форуме славистов Наум Коржавин по иному поводу.
Люди, которые знают, что там и зачем предлагал Алан Кай, — если и станут читать этот текст, то только ради того, чтобы покивать в одних местах и придраться к другим.
Остальные — под ООП понимают то ООП, про которое есть статья в Вики.
Иными словами, я искренне рад, что вы знаете, как правильно, но я не мог оговориться в каждом месте «ООП по Гослингу» — это бы превратило текст в статью из БСЭ.
Какому же утверждению из вики противоречат map и filter? Желательно цитату.
Неужели в микросервисах нет классов и методов? Точно нет?
И чем лямбда отличается от статического метода в ООП?
По-моему, ваши противопоставления слегка высосаны из пальца.
«Я пишу не для славистов, я пишу для нормальных людей»
Эти методы противоречат классическому ООП: они не курочат receiver, но возвращают новый объект.
То что при "классическом ООП методы должны курочить receiver и не возвращать новый объект" даже для славистов перебор. Не думаю, что Гослинг говорил что-то в этом роде.
будем настаивать на правильной терминологии
Программирование не наука и точных определений там нет. Разные уважаемые авторы дают свои определения
Наука там только ФП.
Да и термин ФП вы тут используете весьма фривольно в значении "программирование с использованием процедур первого класса".
А "всё есть функция в жс" - это вообще лютый бред. Похоже широта ваших знаний привела вас к весьма тонкой поверхности.
«всё есть функция в жс» — это вообще лютый бред
Это не я сказал, это Брендан Эйх сказал. Которого позвали в Нетскейп делать Scheme для браузера.
Но вам, конечно, виднее, чем создателю языка.
Вас же не затруднит привести ссылку на источник цитаты, чтобы все могли ознакомиться с её контекстом?
Думаю, он так не говорил напрямую.
А вот про ООП Алан Кей действительно говорил "всё есть объект"
В Javascript
, как раз, всё объект, включая функцию.
А все есть функция – это больше на Haskell
похоже ;)
Мне лень искать прямую ссылку, но вот довольно достойный референс:
Although the lure of Scheme was gone, Brendan Eich still found Lisp-like first-classg functions attractive. Without classes to contain methods, first-class functions provided a toolkit for Scheme-inspired idioms: top-level procedures, passing functions as arguments, methods on objects, and event handlers. The time constraints required deferral of function expressions (also called lambda expressionsg, or just lambdas) but they were reserved in the grammar. Event handlers and object methods were unified by borrowing the this keyword from Java (after C++) in any function to denote the contextual object on which that function was invoked as a method. —https://zenodo.org/records/3707008#.X6XOHVMzbDo
Речь, разумеется, по-прежнему про «начинался как», а не про то, во что оно превратилось сейчас усилиями людей, для которых институтская математика оказалась слишком сложной дисциплиной.
В целом я согласен с выводами.
Возможно конфликт тут в том, что парадигма зачастую описывает общие подходы изучения задачи и описания решения. Потому и языки описания разные и решения могут отличаться.
Смотри на все как на функцию или смотри на все как объект - эти тейки дают разные модели, так же как для дома можно представить разные планы - стен, монтажа, электричества и водопровода.
И это не лишено смысла, эти аспекты ведь самые важные.
Проблемы начинаются тогда, когда выбрана не оптимальная модель или не учтены важные аспекты других моделей.
Скажем, для станции метро критична модель в пространстве - расположение вдоль линии и домов. Для жилого дома - полезные площади. А сталелитейный завод построен вокруг функций - домн, цехов проката и т.д.
Именно из-за этого когда серверные разработчики говорят, что фп идеально, они не врут, но их подход не масштабируется на фуллстейт приложения.
Масштабируется, если уметь его готовить, но будет больше грабель, в сравнении с ООП. А самое главное — разработчики редко бывают полиглотами, и поэтому выбирают парадигму в первую очередь сообразно собственным навыкам, а не предметной модели.
Я не лукавил, когда говорил, что мне лично абсолютно всё равно, какую парадигму выбрать — если мне приходится помочь соседней команде с джавой, я не тащу туда акторную модель, и не буду всеми силами эмулировать чистое ФП на руби, и так далее.
Просто при выборе парадигмы на старте проекта — надо понимать, что каким бы ни был выбор — это не конституция и не библия, некоторые части уместнее написать с использованием более подходящих инструментов.
Выходит Javascript – это чисто АОП ;)
Думаю, что практические программисты не следуют каким-либо парадигмам, и это всё, скорее, дань некой формальной самоотчётности (мол, мы следуем какой-то там парадигме). Важнейшее свойство программного кода — это его работоспособность. А ещё есть читабельность (и поддерживаемость). Довольно читабельный код получается при процедурном подходе.
Если уж и противопоставлять ООП чему-нибудь другому — там это акторной модели.
А нельзя ли немного описать эту самую акторную модель?
ООП языки (не само ООП) плохи тем что
Не запрещают плохого
Не поощряют хорошего
Да ничем они не плохи, кроме того, что были буквально лоббированы очень долгое время корпорациями, по принципу «Если ты не дурак, то для решения любой проблемы — возьмешь ООП».
Сейчас точно так же лоббируется один из самых убогих языков всех времен и народов просто потому, что «Google is too big to fail».
Сейчас точно так же лоббируется один из самых убогих языков всех времен и народов
Это какой такой самый убогий язык?
Да, есть там один…
Go?
Лучше него не так уж много чего, новинки привезли типа дженериков
Rust классный, но сложный, с библиотеками плохо, разве что в сложных случаях питоновский или сишный код из-под rust запускать
C# остановился в развитии
Java тем более
Python для дата аналитиков и прочих, для какого-нибудь ответственного корпоративного приложения не годится
PHP кроме России уже нигде не нужен
1С для одной специфичной системы
Ваша система ну очень для небольшой доли рынка
Go?
Да что Вы, разве маэстро мог обозвать go убогим?
Что значит «остановился в развитии»? Зачем и куда языку развиваться, если он сделан с умом?
Не, если ты только спустя 15 лет поддержки языка вдруг понимаешь, что «кооперативная многозадачность» и «язык, чтобы никто не мог напортачить» — парой не ходят, а зашедшие не совсем неофиты все время бубнят про дженерики…
Но если язык нужно развивать (а не ускорять и оптимизировать) — это и есть первый звоночек, что с языком что-то не так.
P. S. система не моя, но если бы её сделал гугл — миру сейчас было бы в триста раз легче написать что-то конкурентное.
Что значит «остановился в развитии»? Зачем и куда языку развиваться, если он сделан с умом?
А чем тогда соответствующему комитету заняться? О чём им заседать?
Признаюсь, что если я раньше считал, что неплохо знаю плюсы, то с внедрением новых стандартов точно уже нет.
Не, если ты только спустя 15 лет поддержки языка вдруг понимаешь, что «кооперативная многозадачность» и «язык, чтобы никто не мог напортачить» — парой не ходят,
Go мне нравится как раз интеграцией поддержки кооперативной многозадачности на уровень языка. Считаю, что это и есть очень неплохо реализованная киллер-фича Go.
а зашедшие не совсем неофиты все время бубнят про дженерики…
Это да. И то, как дженерики нынче в Go реализованы, вызывает некоторое недоумение. Ещё раздражает отсутствие полиморфизма параметров.
Но если язык нужно развивать (а не ускорять и оптимизировать) — это и есть первый звоночек, что с языком что-то не так.
Справедливости ради, никакой из языков не избежал внесения изменений. Или плодятся диалекты. Или в новую жизнь под новым именем
Go мне нравится как раз интеграцией поддержки кооперативной многозадачности
Недавно в Go все-таки завезли вытесняющую. Вы уверены, что вам нравится именно кооперативная? Её же любой джун может отыквить одним взмахом руки.
никакой из языков не избежал внесения изменений
Ну ээээ… В эрланге единственным изменением за 30 с лишним лет — было добавление мапов на уровне языка. А вытесняющая многозадачность (и всё остальное) — были с конца 80-х.
Да, появился эликсир, ради блистательного языка макросов. Есть LFE, и даже Gleam, оба работающие на BEAM. Но вся эта история — больше про синтаксис, так-то стандартной библиотеке (OTP) и рантайму — четвертый десяток пошел, чуваки исключительно оптимизациями и починкой редких багов заняты.
Вы уверены, что вам нравится именно кооперативная? Её же любой джун может отыквить одним взмахом руки.
Ага. Абсолютно. Люблю кооперативку и фулстек корутины.
А то что любой джун может отыквить , так лучше если это будет заметно сразу, ещё на тестах, чем тихо при вытесняющей будет отъедать ресурсы в проде.
Да, появился эликсир, ради блистательного языка макросов.
На мой непросвещённый взгляд, Эликсир - логичное развитие Эрланга. И да, он клёвый.
Но вся эта история — больше про синтаксис,
Развитие языков это всегда про синтаксис
Вот c# f# уже дофига лет, а если попробовать объединить их в одном проекте (функциональное ядро, императивная оболочка) оказывается что библиотеки не совместимые (списки) и надо делать порты и адаптеры. Сразу всё настроение упало.
кооперативная многозадачность редко нужна имхо, разве что операционной системе
А в приложении создаём список задач, данных для них и кидаем работникам. А объединяем результаты уже как положено в concurrent dictionary,а лучше вообще в БД
А объединяем результаты уже как положено […]
Эм… Вы сейчас прямо перечеркнули ценность того, чем я занимаюсь последние несколько лет. Для этого и горутины не нужны, можно на тредах, как в питоне и руби десять лет назад, накостылить.
Горутины нужны для другого: они могут жить вечно, и их может быть сотня тысяч, каждая — обслуживает свою сущность.
Разверну мысль
ООП предоставляет разработчикам слишком много инструментов и вариантов, не налагая правильных ограничений. Несмотря на обещания ООП рассмотреть модульность и улучшить возможность повторного использования, оно не выполняет свои обещания (подробнее об этом позже). ООП-код поощряет использование разделяемого изменяемого состояния, которое может быть небезопасно от раза к разу. ООП обычно требует большого количества бойлерплейта (низкого отношения сигнал/шум).
https://tproger.ru/translations/oop-the-trillion-dollar-disaster
Вчера — отлучали от церкви за неверную парадигму. Сегодня — сжигают на костре за неточный термин. Эволюция фанатизма.
"Круглое - таскаем, квадратное - катаем" а чё такого? Ну не правильные термины, делов то.
Да, ‘круглое таскаем’ — и чё?
Статья без примеров кода в каких случаях одна парадигма лучше другой, но при этом делающая какие то выводы в этом направлении - мусор. Научность статьи - нулевая.
Если нет ни одного примера кода, когда классическое ООП лучше чем ФП - значит оно никогда не лучше.
А неудачные попытки написать такие примеры можно найти в статье https://habr.com/ru/articles/885980/
Причем неудачные - все.
А я и не претендую на «научную статью». Это же хабр, а не серьезный форум по программированию, какие вообще примеры кода. «Статья», ха. Так, текстик.
Если нет ни одного примера кода, когда классическое ООП лучше чем ФП - значит оно никогда не лучше.
Оно не лучше. Оно другое.
Вот есть известная книга Банды Четырёх где приводятся конкретные примеры решения конкретных задач на ООП - это классика. - Перевести решение этих же задач на функциональное программирования никому не удалось. Хотя книг по функциональному программирование полно.
Насколько я понял - есть задачи решаемые на ООП и есть решаемые функционально. И они фактически мало пересекаются между собой.
Так что книги такой, где решались бы задачи из книги Банды Четырёх функциональными методами (способами, патернами) сейчас нет. Не выпущено и не написано.
Ну, это тоже крайне сомнительный тезис. Если бы мне лично было это интересно, и у меня был бы вагон лишнего времени, даже я бы легко такую книгу написал.
Не существует задач, решаемых только в одной парадигме, — на то она и парадигма.
Если бы мне лично было это интересно, и у меня был бы вагон лишнего времени, даже я бы легко такую книгу написал.
Окей. Вагона у вас нет, но нет вагона и у других, раз книги такой нет. До сих пор. Но есть ChatGPT. Его и спросим:
Возьмём программу "разузлования". На чистом ООП она выглядит, по мнению ChatGPT так:
class Component:
"""Класс, представляющий компонент (узел или деталь)."""
def __init__(self, name, quantity=1):
self.name = name
self.quantity = quantity
def explode(self):
"""Возвращает список компонентов самого себя."""
return {self.name: self.quantity}
class Assembly(Component):
"""Класс, представляющий узел, содержащий другие компоненты."""
def __init__(self, name, components):
super().__init__(name)
self.components = components # список кортежей (Component, количество)
def explode(self):
"""Разузлование узла: рекурсивно раскрывает все его компоненты."""
exploded = {}
for component, qty in self.components:
sub_explosion = component.explode()
for sub_name, sub_qty in sub_explosion.items():
exploded[sub_name] = exploded.get(sub_name, 0) + sub_qty * qty
return exploded
# Определяем детали
bolt = Component("Болт", 4)
nut = Component("Гайка", 4)
plate = Component("Пластина", 2)
# Определяем узлы
sub_assembly = Assembly("Малый узел", [(bolt, 2), (nut, 2), (plate, 1)])
main_assembly = Assembly("Главный узел", [(sub_assembly, 2), (bolt, 1)])
# Разузлование изделия
result = main_assembly.explode()
print(result) # {'Болт': 5, 'Гайка': 4, 'Пластина': 2}
В этом решении используется композиция классов. Метод explode рекурсивно раскрывает структуру изделия, суммируя количества компонентов.
Функциональный вариант:
from collections import defaultdict
# Определение спецификации изделия в виде списка (узел -> [компонент, количество])
specification = {
"Главный узел": [("Малый узел", 2), ("Болт", 1)],
"Малый узел": [("Болт", 2), ("Гайка", 2), ("Пластина", 1)],
"Болт": [],
"Гайка": [],
"Пластина": [],
}
def explode(component, spec, multiplier=1, acc=None):
"""Функция разузлования изделия."""
if acc is None:
acc = defaultdict(int)
if component in spec:
for sub_component, qty in spec[component]:
explode(sub_component, spec, multiplier * qty, acc)
acc[component] += multiplier
return acc
# Разузлование изделия "Главный узел"
result = explode("Главный узел", specification)
# Убираем из результата корневой узел
result.pop("Главный узел", None)
print(dict(result)) # {'Болт': 5, 'Гайка': 4, 'Пластина': 2}
Здесь explode — рекурсивная функция, которая берет компонент, смотрит его состав, вызывает саму себя для всех подкомпонентов и суммирует их количества в аккумуляторе (acc). Используется defaultdict(int), чтобы избежать лишних проверок.
Вывод от ChatGPT: Оба подхода дают одинаковый результат, но ООП лучше подходит для сложных моделей с поведением, а функциональный стиль — для краткости и простоты.
Можно согласится с его выводом. Также объект может быть типа "чёрный ящик" в ООП - количество он может запрашивать где угодно (по сети от сервера, брать из базы или запрашивать у оператора) - при этом, усложнение объекта никак не влияет на саму программу (сам текст) разузлования. - это очень крутая сила ООП. Да и сам объект может "прибывать" из сети, из базы и т.д.
Я думаю книги нет именно из-за того, что никто не может явно показать преимущество функционального подхода для тех паттернов что есть в книге Банды Четырёх. А просто констатировать что можно написать тоже, но в функциональном стиле, но не показать что это будет лучше - как-то и смысла нет в таком написании. Поди.
А я думаю, что книги нет потому, что никому не впёрлось переубеждать низкооплачиваемых бедолаг с ООП наперевес; чем их больше, и чем они твёрдолобее, — тем нам выгоднее за ними всё переписывать, когда оно отыквится на действительно больших объёмах, превратится в неподдерживаемую кашу и начнутся поиски консультанта, который хоть как-то поможет вылезти из болота.
Сгенерированный код на питоне никакого отношения к ФП не имеет. Выводы GPT меня не интересуют, я не имею привычки спрашивать совет у автодополнения.
А я думаю, что книги нет потому, что никому не впёрлось переубеждать низкооплачиваемых бедолаг с ООП наперевес; чем их больше, и чем они твёрдолобее,
Не, "теория заговора" - это несерьёзно.
Сгенерированный код на питоне никакого отношения к ФП не имеет.
А вот то, что к коду ООП на питоне у вас нет претензий - это любопытно. - Может книги с функциональщиной паттернов Банды Четырёх нет потому, что каждый функциональщик считает код другого функциональщика не совсем "кошерным" ("чистым") для написания такой книги то?
книги такой, где решались бы задачи из книги Банды Четырёх функциональными методами (способами, патернами) сейчас нет
Это как неуловимый Джо: его никто не может поймать потому что он нафиг никому не нужен.
Задачи из книги Банды Четырёх функциональными методами в ФП решаются элементарно
Чтобы не быть голословным спросим Ктулху
https://LLMshare.syntxai.net/e569934c-0c6e-74ee-8d673333
https://LLMshare.syntxai.net/6179f457-ff6c-2c69-56aeaaa2
https://LLMshare.syntxai.net/4f5916fa-1448-27ba-8835f963
И сравнение
https://LLMshare.syntxai.net/efe5b365-3ca1-cbeb-b1555980
https://LLMshare.syntxai.net/d9183849-9b09-e7e9-f1eadda3
Тут самому надо вкурить что он там написал...
Задачи из книги Банды Четырёх функциональными методами в ФП решаются элементарно
Но книги то нет. Такой.
Что касается "элементарно", то вполне возможно. Но, как понял из сравнения- выбор зависит от ментальности архитектора. Если он думает объектами, то он выберет парадигму ООП, если он сразу освоил функциональщину, то он выберет ФП.
Но надо отметить, что объект хорош тем, что его можно ментально представлять как "чёрный яшик", что наверняка становится определяющим для сложных систем, где системы обращаются к объектам, вызывая их методы, при этом объекты могут иметь сотни разных реализаций этих методов внутри объекта что позволяет легко вводить разные реализации объекта, никак не затрагивая при этом те системы, что используют эти объекты.
Частично да
Поэтому я стараюсь привить себе функциональное мышление
Могу ошибаться, но мне показалось, что за, в принципе, хорошо изложенным содержанием скрыта изрядная доля самолюбования автора самим собой....
Парадигма — религия, или наука?