Обновить
99
0.1
Роман Смирнов @Source

Head of Elixir at Ecom.tech

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

Из ваших высказываний получается, что логика такая: нет систем, которые бы я знал и где соблюдался этот принцип => принцип не нужен
Не совсем, во-первых системы есть. А во-вторых, логика такая: увеличение уровня чистоты принципа не даёт соразмерного увеличения практической пользы. И даже наоборот отход от чистоты частенько позволяет решать задачи эффективнее.
К примеру, b squared — чище, b * b — понятнее
a +: b — чище (только не работает почему-то),
a + b — понятнее.
Вот, как раз некоторые считают, что дефолтное состояние человека — воспринимать окружающий мир и все сущности в нем как объекты: идентифицировав объект, мы начинаем пытаться на него воздействовать и смотреть, что же будет в ответ.
Как минимум, мы отличаем объекты с поведением (акторы) от объектов без поведения (данные) и принципиально по-разному к ним относимся. Благодаря чему у нас не возникает дилеммы «человек пишет ручкой» или «ручка пишет, используя человека».
Понимаете, наличие синтаксического сахара говорит о том, что концепция в чистом виде не слишком удобна и/или трудна для понимания. И тут встаёт выбор «вам шашечки (чистоту концепции) или ехать (возможность эффективно решать задачи)».
То, что теоретически что-то возможно, не делает это автоматически удобным для всех. C Lisp похожая ситуация, концепция изящна и удивительно проста. Но для легкости восприятия требуется либо отходить от привычного мышления, либо увешиваться синтаксическим сахаром.
Поэтому ни Smalltalk, ни Lisp и не захватили мейнстрим… среднестатистическому программисту банально не удобно с любой униформностью. Да и в физической реальности нас окружает наблюдаемое многообразие, а униформность остаётся теоретической концепцией.
Ok, пусть будет так:
Enum.reduce(1..n, 0, &(&1*&1 + &2))

чтобы без фокусов )))
Лично для меня, придание примитивным типам объектности, всегда имело смысл не в том, чтобы, собственно, работать с примитивными типами, как с объектами, а в том, чтобы иметь возможность работать с объектами, как с примитивными типами.
Хорошее дополнение в дискуссию. На мой взгляд, для расширения примитивных типов хватит и структур, над которыми имеется возможность определить любые операторы. Так ведь?

я ни разу не замечал, чтобы мне, например, в C# делать арифметику со встроенными типами было сложнее, чем в Си.
Загляните в IL-код, там нет никаких объектов для чисел. Но не задумываясь о разнице между числами и объектами, Вы легко можете написать код, где в цикле возникнет какой-нибудь box int32. И удар по производительности обеспечен. Смысл не в том, что нельзя работать с числами как с объектами. Смысл в том, что нельзя забывать, что число — это число, а объектом оно только притворяется. Поэтому переключение сознания между объектами и примитивными типами данных неизбежно для написания нормального кода.
Я понимаю, тут постановка задачи — показать несостоятельность ООП подхода
Нет, Вы вообще не поняли, что мы в этой ветке обсуждаем (невозможность униформности на всех уровнях системы), и даже статью, видимо, не дочитали.

но, например, плюсы
В Вашем примере куча не-ООП… 0 — это не объект в плюсах, for — не метод, +, * и даже return — это тоже не методы. Так что на униформную ООП-реализацию это точно не тянет.
Очень лаконично всё описывают.
А вот это Вы зачётно пошутили )))
Есть ведь разница между «меня не интересует» и «ООП не интересует»? Я сомневаюсь, что ООП обладает сознанием, но даже если так, то со мной своими переживаниями не делится.
Не придирайтесь… Это всего лишь сокращение для «Во время применения ООП нас не интересует»

мне не приходится постоянно переключать «режим» сознания при работе с сущностями различного рода. Понимаете?
Честно говоря, не понимаю в чём проблема. Мы в жизни постоянно переключаемся между сущностями различного рода, можно сказать, это дефолтное восприятие человека. Вы по-любому переключаетесь, когда говорите о массивах, строках, числах. Просто делаете вид, что это типа тоже объекты. Если бы можно было бы оставаться всегда на уровне объектов, не переключаясь, Вы бы названия обычных типов данных вообще забыли бы.

(0 to: n) reduce: [:a :b | a + b squared].
Кхм, и в каком месте тут униформность?
если вызов метода записывается как
object method: arg
то что такое квадратные скобки? что такое a + b? что такое b squared? что такое ":a :b |"?
Даже реализация такого микропримера совсем не униформна, о каком отсутствии «переключений» тогда вообще говорить…
Да мне не интересно, что там «внутри»
Вот! Именно это я Вам вчера и писал!
ООП не интересует что там внутри. В нашем случае внутри акторов: ФП и обычные типы данных.

Даже когда буду не то что коллекцию обрабатывать, а банальный цикл или даже «if» писать — все равно буду объектам слать сообщения.
И какому же объекту уйдёт ваше while или if сообщение? Я понимаю, что можно фантазию подключить и выдумать вспомогательные объекты. Вопрос только нафига?

Вы меня реально за идиота принимаете? Уже не в первый раз притом :) Вы действительно считаете, что я не понимаю, что рекурсия где-то должна кончится?
Я просто не понимаю, почему Вы считаете принципиальным на каком моменте эта рекурсия закончится.
Вот на мой взгляд, добавление к числу объектного поведения капитально усложняет работу с числами, зачем тогда мне рекурсивно превращать их в объекты?
Попробуйте в ООП-стиле написать код для вычисления суммы квадратов натуральных чисел от 1 до n. Для примера реализация на Elixir:
Enum.reduce(1..n, &(&1*&1 + &2))
Это не странно. Это просто неизбежное нарушение концепции «всё есть объект». Не можете Вы послать объекты ни в файл, ни в реляционную БД, там будет что угодно: строки, бинарные последовательности, числа, массивы, но только не объекты :-)
Наличие хотя бы автораспаковывания/упаковывания данных необходимо для всех вышеперечисленных задач.
Ну да, оборачивать всё в монады и смиряться с побочными эффектами, куда уж проще… Хотя допускаю, что при определенном типе мышления, и это может стать простым.
Однако что одна, что другая идея на практике не реализуема на 100%. Программа без побочных эффектов никому не нужна. То же самое и с объектами, программа, которая работает только с объектами — это вещь в себе, она не пишет в файлы, не рендерит странички в html, не принимает пользовательский ввод, не пишет в БД (хотя может ООСУБД ещё кто-то использует?) и т.д.
Да, всё верно. Внутри «объекта» у нас сплошное ФП :-)
Впрочем если хотите некую композицию «объектов», то это тоже не вопрос, стартуйте нужный процесс из обработчика сообщения.
Плата за создание процесса не так велика, оверхэд примерно того же порядка как при создании объектов в Java.
В общем, смысл в том, чтобы в качестве объектов рассматривать только те сущности, которые реально живут какой-то своей жизнью. У которых есть понятный жизненный цикл или миссия «бесконечно» обрабатывать некоторые запросы.
Всё остальное — это просто данные, которые обрабатываются при помощи ФП.
Другими словами «протащить» объекты максимально далеко в бутстрэппинг?
Кстати, Erlang позволяет посылать сообщения процессам на удалённых нодах, их даже никуда тащить не надо и тем более раздваивать. Вот только ответ на сообщение придёт в виде данных. Что весьма удобно на практике, но не вписывается в Вашу теоретическую концепцию.
В принципе я понял Вашу позицию. Для Вас «всё есть объект» имеет некий практический смысл. А в моей картине мира это лишь интересная теоретическая идея, типа абсолютно чистого функционального языка.
На практике зачастую вырождающаяся в «объекты ради объектов» и «чистоту ради чистоты». Как говорится, гладко было на бумаге, да забыли про овраги.
Сами найдёте. Не великий труд, всё на вики есть.
Раз уж Вы сослались на вики, то откройте страничку Programming paradigm и увидьте, что модель акторов — это такая же реализации ООП, как и Class-based и Prototype-based:

К тому же в статье обсуждается ООП в контексте изначального смысла. Цитаты от автора этого термина на тему каким должен быть язык, реализующий ООП, можно найти под спойлером в начале статьи. Как видите, ни о каких «китах» там нет ни слова. Разве что про инкапсуляцию и то, только в плане сокрытия данных.
Собственно, мне нечего добавить, кроме ссылки на доку
lair уже абсолютно правильно ответил.
Так а разве кто-то с этим спорит? В статье вместо структуры Student вообще используется просто строка для упрощения примера. Но от замены на структуру код вообще не изменится, только в паре мест name на student заменить надо будет.
Ну и вызывающий код незначительно поменяется:
school |> add_student(%Student{name: "Aimee"}, 2)
Ну, прикольное видео… Только оно как раз скорее про Java, а не про ООП в изначальном смысле. Я досмотрел до момента, когда он нарисовал дерево супервизоров и сказал, что нормальная инкапсуляция возможна только в таком случае, но так никто не пишет. Забавно, что на Erlang/Elixir практически только так и пишут, даже есть отладочный инструмент, который эти деревья визуализирует, observer называется.
image
Есть. Но без усердного пиара. А так, инкапсуляция в плане сокрытия гораздо лучше как раз в модели акторов реализована на мой взгляд.
Ещё и композиция есть. Наследование же давно уже не в почёте xD
школьник лишь некая запись, с которой можно работать как с объектом, любая функция которая изменяет внутренее состояние школьника, возвращает новый «объект» школьника.
В Elixir для этого есть структуры, которыми и оперируют «ORM» типа Ecto. В Erlang для этого же есть записи.
И как правильно заметил lair в статье нет никакого призыва использовать акторы вместо структур. Зато есть призыв с точностью до наоборот, не тащить ООП на уровень, где оно не нужно. В вашем примере функции будут работать со структурой Школьник, как со структурой, а не как с объектом. Грубо говоря, примут на вход одну структуру, а на выход вернут совсем другую.

Информация

В рейтинге
4 057-й
Откуда
Россия
Зарегистрирован
Активность