Pull to refresh

Comments 181

UFO just landed and posted this here
у ФП тоже нет разделения — в нем есть только функции, а все «данные» — это параметры на входе в функцию и результаты на выходе из функции.

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

Понимаете, какая штука. Существует два понятия ООП. Одно — "общепринятое ООП" и другое — "ООП в Smalltalk", которое существует только в контексте истории и каких-нибудь специфических языков.
Термины людям нужны для однозначного общения друг с другом. Пока основная масса людей под сокращенным термином "ООП" понимает именно общепринятую версию с инкапсуляцией, наследованием и полиморфизмом, то ни о каком "искажении" речи быть не может. Пока основные промышленные языки используют И.Н.П., пока на собеседованиях у джунов спрашивают про ООП и считают ответ про И.Н.П. верным, все останется на своих местах.


У Erlang же вроде не ООП, а модель акторов. Зачем отвоевывать занятый термин, если существует свой уникальный?

Ну, давайте посмотрим на определение общепринятого ООП:


Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data, in the form of fields (often known as attributes), and code, in the form of procedures (often known as methods). A feature of objects is an object's procedures that can access and often modify the data fields of the object with which they are associated (objects have a notion of "this" or "self"). In OOP, computer programs are designed by making them out of objects that interact with one another.

Как видите, никакого противоречия с "ООП в Smalltalk" тут нет.
Не знаю уж, кто первым придумал ассоциировать ООП с И.Н.П. и рассказывать студентам про 3 китов. Но этот человек явно заслужил премию "почётный диверсант" за введение в заблуждение огромного количества людей. Причём, насколько я замечал, эта дезинформация гораздо популярнее в РуНете.

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

Спасибо, это очень удачная фраза для описания тех мыслей что меня иногда посещают )

А по поводу рунета — я смотрю на эту статью — medium.freecodecamp.org/object-oriented-programming-concepts-21bb035f7260, и вобщем то на много других с медиума, и там всё так же грустно.

Русским студентам все же ближе русская Википедия, в которой написано


Объе́ктно-ориенти́рованное программи́рование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования[1].

Это определение подразумевает И.Н.П. и ссылается на книгу Грэди Буч. Объектно-ориентированный анализ и проектирование с примерами приложений на С++ = Object-Oriented Analysis and Design with Applications / Пер. И.Романовский, Ф.Андреев. — 2-е изд. — М., СПб.: «Бином», «Невский диалект», 1998. — 560 с. — 6000 экз. — ISBN 5-7989-0067-3.


Позже посмотрю как у него в оригинале даётся определение ООП. Может скопировали не так, может переводчики исказили. Ну а может Грабли Буч и есть тот диверсант. =)

Русским студентам все же ближе русская Википедия, в которой написан

Русским(и не русским) студентам ближе заучить первое попавшееся определение ради галочки в своём портфолио, и чтобы на зачете было что рассказать, а не вникать что же это такое и зачем нужно Ж)
Ну а может Грабли Буч и есть тот диверсант. =)

Мне пока кажется, что понятие просто искажалось и сужалось с новых к привычным вещам постепенно. Но Буч вещал именно об искаженном понятии. Его определение из 3-его издания книги:
Object-oriented programming is a method of implementation in which programs
are organized as cooperative collections of objects, each of which represents an
instance of some class, and whose classes are all members of a hierarchy of
classes united via inheritance relationships.

Он же, кстати, внёс свой вклад(написал книгу) в популяризацию UML, что, по сути, выставление классов и их иерархий во главу угла.

Ну и ещё, свой вклад в сие неблагородное дело явно внёс Страуструп, называя свой язык ОО, и плотной ассоциации идеологии классов и стандартных «трёх китов»(+ абстракцию) с данным понятием.
What is ‘‘Object-Oriented Programming’’? (1991 revised version), Bjarne Stroustrup — www.stroustrup.com/whatis.pdf

The general idea is to equate ‘‘support for data abstraction’’ with the ability to define and use new types and equate ‘‘support for object-oriented programming’’ with the ability to express type hierarchies.

The basic support a programmer needs to write object-oriented programs consists of a class mechanism with inheritance and a mechanism that allows calls of member functions to depend on the actual type of an object

И, вобщем, там ещё 20 страниц такого описания. Кстати, со ссылками в конце, в том числе на некоторые источники с информацией 1986 года об ООП.
Ну и ещё, свой вклад в сие неблагородное дело явно внёс Страуструп, называя свой язык ОО, и плотной ассоциации идеологии классов и стандартных «трёх китов»(+ абстракцию) с данным понятием.

Кстати, вполне возможно, что он и есть тот самый "диверсант", поскольку он начал позиционировать C with classes как объектно-ориентированный язык, коим он не являлся. А учитывая популярность C, ему удалось, как сейчас говорят, хайпануть на этой теме и завести IT-индустрию в многолетние мучительные поиски паттернов и антипаттернов, чтобы хоть как-то этим безобразием можно было пользоваться. А с приходом мультиядерных процессоров опять всё сломалось… Вдруг выяснилось, что shared data — это больно и вокруг этого нагородили ещё кучу костылей.


На фоне всего этого, Армстронг и вся команда разработчиков Erlang — просто гении, обогнавшие развитие индустрии на десятилетия.

В принципе, любое определение ООП, в котором есть слово "класс", уже неверно. Хотя бы потому что классы — это все-лишь один из способов реализации ООП. Соответственно все такие определения нарушают open-closed principle xD


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


Как видно, модель акторов, классы, прототипы и т.д. — всё это просто разные реализации ООП. И ООП — это только то, что их объединяет.

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

Нуу… Я считаю иначе.
Популярное заблуждение != новый стандарт. Я не смог найти внятного определение «общепринятого ООП», и кто этот термин вообще ввёл. Тем более неясны преимущества такого подхода, и как оно вообще отличается от того что было раньше.
Почему адепты данного «классического ООП» не называют язык Си объектно-ориентированным? В нем ведь вполне реализуются все 3 этих принципа. В нем есть полиморфизм в виде возможности передачи указателей на функции, в нём есть наследование(да, по этому пункту, одному из 3-х, всё же есть отличия, тут у совеременных «классических» языков есть преимущество), но ведь зато у Си есть преимущество в инкапсуляции. Если под инкапсуляцией мы имеем ввиду складывание данных и функций в одном месте, то Си изначально не даст доступ к данным одного модуля(файла) из другого модуля(файла), пока мы явно не укажем доступ в заголовочном файле.

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

Причем я не считаю что людям срочно всем нужно идти учить, читать, что такое ООП от Алана Кея. Тут большая проблема в том, что людям навязывается ООП. Если кто-то скажет что он не знает что такое ООП — на него посмотрят да скажут «А я думал ты программист!? 0_о», а новичку первым же делом будут советовать — выучи, выучи главное ООП. А он пойдет и выучит, выучит что ООП это инкапсуляция наследование и полиморфизм. Только вот LSP он не выучит, «Composition over Inheritance» он тоже не выучит. Польза то какая от всего этого?
Для новичков это часто отражает, наконец то, отход от стиля написания кода всей программы в одном файле, или в какой-нибудь main() процедуре. Но в таком случае, то что ему нужно называется скорее Объектно-ориентированный дизайн. Это как раз полезные идеи из ООП, которые можно применять в нашем коде.

У Erlang же вроде не ООП, а модель акторов. Зачем отвоевывать занятый термин, если существует свой уникальный?

Да, вы правы, просто модель экторов весьма близка к идеям ООП, по которому Кей даже сокрушался, что стоило бы назвать его message-orientied programming. Идея данных высказываний лишь в противопоставлении. То есть, что Эрланг с его Actor model ближе к идеям ООП чем какая-нибудь Java.
А под инкапсуляцией адепты И. Н. П. понимают три идиотских слова «public, protected, private», ничего больше.
Да и с private у них большие проблемы, потому, что после того, как написано слово private все приватные члены снабжаются public геттерами и сеттерами.

Так известно же, что ООП/ФП — это ФП/ООП для бедных.

«Concurrency is not parallelism». Не думаю, что Армстронг говорил про параллелизм, а не конкурентность (надо источник посмотреть)
Эрланг утилизирует все ядра машины, так что параллелизм достигается буквально из коробки.
Так было не всегда. И даже сейчас миллион потоков не работают параллельно, на миллионах ядер. Отсюда и известный доклад «конкурентность — не параллелизм»
Я к тому, что паралелизм и конкурентность не взаимоисключающие понятия. Они, скорее, существуют параллельно и дополняют друг-друга. Говоря о конкуррентности нельзя не говорить о параллелизме, нынче все системы многоядерные все же. Говоря о паралелелизме нельзя не говорить о конкурентности — не в идеальном мире живем. Как-то так, надлеюсь понятно пояснил свое высказывание.

Почитал оригинал — используется слово concurrent и никак не parallel, ну а на эту тему делал замечательный доклад Роб Пайк (хоть и в контексте языка Го, но тем не менее).


Перевод:


Теперь вопрос – хотите ли вы обработать 10 000 пользователей в одном потоке, используя коллбеки для эмуляции параллелизма, или вы все же хотите создать 10 000 параллельных процессов, каждый из которых прост и не нуждается в коллбеках вовсе?

Источник:


Now would you like to handle 10,000 users in a single thread using callbacks to emulate concurrency or would you like to make 10,000 concurrent processes, each of which is simple and has no callbacks.
«один web-сервер с 10 000 пользователей»
Которые ничего не делают, а просто подключены! Throughput близок к нулю.
Это конечно достижение, но очень сомнительное.
Что значит «просто подключены»? Они подключены, они посылают сообщения, сообщения обрабатываются и ответ возвращается — и все это может происходить разом на нескольких машинах, что бы обеспечить ту самую пропускную способность.
>они посылают сообщения
как часто?
> сообщения обрабатываются
Ага, ага. Сами-то пробовали?
Пробовали, в эрланге т.н. гринтреды и они так работают
как часто?

По мере надобности.

Ага, ага. Сами-то пробовали?

Да, пробовали.

В чем, собственно, вопрос-то? В том хватит ли аппаратной мощности на обработку 10К коннектов? Может хватить, может не хватить — зависит от «тяжести» вычислений и того, какая аппаратная часть. Или вопрос в том, могут ли 10К потоков работать независимор в рамках одной vm? Да, могут — в этом и смысл Эрланга вообще говоря.
Автору респектище и земля пухом. Переводчику — спасибо. Статья отличная и архиполезная!
…Но меня мучает ряд вопросов по поводу:
К сожалению, хоть первый успешный объектно-ориентированный язык на основе этой модели (Smalltalk) и оперировал понятиями «объект» и «сообщение», но последние в Smalltalk были не настоящими сообщениями, а лишь замаскированными синхронными вызовами функций.
Что не так с сообщениями в Smalltalk? Сообщения в ООП обязательно должны быть асинхронными и, если так, то почему? Или тут упор на «замаскированные вызовы функций»? Бывают другие варианты? В Erlang/Elixir это не так? А как?
Мысль автора скорее в том, что передача сообщений должна быть такой, какую ожидает иметь отправитель — синхронной или асинхронной. Smalltalk видимо предоставил только первый вариант и в этом претензия к нему.
То есть, претензия к языку заключается в том, что он не реализовал в себе все возможные варианты всего сущего? :) Честно говоря, сомневаюсь, что автор именно это имел ввиду. Аналогично тому как в Erlang/Elixir «gen_server позволяет нам эмулировать оба поведения», в Smalltalk можно реализовать поведение, которое складывает полученные сообщения в почтовый ящик и тут же возвращает управление отправителю.
И всё же такое поведение нельзя назвать синхронным. А если получатель упал не успев сообщить отправителю? В том-то и дело, что в Erlang асинхронность отправки сообщений между акторами является базовым вариантом, а уже синхронность эмулируется. Сообщения отправляются по принципу «выстрелил и забыл» и добавление любого ожидания ответа от получателя эту асинхронность ломает.
А если получатель упал не успев сообщить отправителю?
Отправитель получить исключительную ситуацию и может ее обработать — управление все равно вернется. Поведение, заданное как поведение «по умолчанию» в Erlang-е, в Smalltalk-е реализуется в рамках «библиотеки». Там есть куча всяких нюансов, не позволяющих сделать Smalltalk таким, каким он должен был бы быть, но, понимаете, подход такой: язык как можно проще (тут еще есть куда стремиться), все остальное — реализуется на этом языке.

Кстати, некоторые называют это моделированием и обозначают как основную (объединяющую всех) идею ООП — еще одно определение? :)
Да, отправитель может обработать это исключение. Там же наверное и таймаут ожидания ответа будет. Но ведь именно об этом Джо Армстронг и пишет ниже, ратуя за простоту обмена сообщениями, простоту самих процессов-акторов и обработку ошибок вне процессов. Т.е. такие «инфраструктурные» сложности противоречат тезису Джо о том, что перечисленные выше атрибуты необходимы для распределённых и надёжных систем. В этом контексте он и указал на это, как на минус Smalltalk'а.
Другое дело, что этот тезис можно поставить под сомнение. Но я не буду, так как скорее согласен с ним, да и Erlang/Elixir доказал, что на нём можно реализовывать такие системы малой кровью (сравнительно с другими).
…необходимы для распределённых и надёжных систем. В этом контексте он и указал на это, как на минус Smalltalk'а
Если бы речь была о том, что Erlang имеет преимущества перед Smalltalk в плане реализации распределенных систем — я бы не стал задавать дурацких вопросов. Но — перечитайте цитату еще раз — речь идет о том, что центральная для ООП и для Smalltalk концепция сообщений реализована в последнем как-то неполноценно. Аргументы, что конкаренси и параллелизм это круто, здесь не играют роли — разговор про ООП. Я вот и пытаюсь понять, в чем же претензии к реализации сообщений в Smalltalk — с точки зрения ООП, не распределенных систем и прочих посторонних вопросов совершенно другого уровня?
Что не так с сообщениями в Smalltalk?

В Smalltalk, строго говоря, вообще нет отдельной концепции сообщений. Т.е. говорить о сообщении как о чём-то независимом от объекта там можно только в теории.


Бывают другие варианты? В Erlang/Elixir это не так? А как?

В Erlang/Elixir каждый объект (актор) имеет свой mailbox, куда приходят сообщения, и он их по очереди обрабатывает. Ну и 2 режима отправки сообщений: ждать результат обработки сообщения от объекта или не ждать.

Вообще говоря режим один — не ждать обработки сообщения, но gen_server позволяет нам эмулировать оба поведения
В Smalltalk, строго говоря, вообще нет отдельной концепции сообщений.
Как это?!? Если говорить о Smalltalk как о языке, то сообщения лежат в основе его синтаксиса — разве это не та самая «концепция»? Другими словами (если отбросить несколько исключений), Smalltalk — это и есть сообщения. Если речь о более «физическом» воплощении концепции сообщений, то ее можно даже «пощупать» — см. класс Message :)

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

В этом есть что-то «плохое»? Или речь вообще о чем-то другом?

В Erlang/Elixir каждый объект (актор) имеет свой mailbox, куда приходят сообщения, и он их по очереди обрабатывает. Ну и 2 режима отправки сообщений: ждать результат обработки сообщения от объекта или не ждать.
Про это я в курсе, но чем это принципиально отличается от того, что есть в Smalltalk? Настолько принципиально, что в Smalltalk это сделано неправильно («не настоящими сообщениями, а лишь замаскированными синхронными вызовами функций»), а в Erlang — правильно? Я, кстати, так пока и не понимаю, что же такое сообщения в последнем: просто какая-то еще одна умозрительная (теоретическая?) концепция, не имеющая воплощение в самом языке, описанная где-то за его пределами и искусственно привнесенная в него. Нет?
Как это?!? Если говорить о Smalltalk как о языке, то сообщения лежат в основе его синтаксиса — разве это не та самая «концепция»?

Разве "сообщение" в Smalltalk — это не объект? А оно обязано быть не объектом, чтобы быть чем-то иным по факту, а не на словах.

Не понял, кому обязано?

Здравому смыслу :-)
Нельзя сказать, что объекты обмениваются сообщениями, если сообщения — это тоже объекты. Получается, объекты обмениваются объектами, а точнее не обмениваются, потому что ответное сообщение невозможно отправить тому, кто прислал входящее. Короче, бардак: нет ни обмена сообщениями, ни самих сообщений, как отдельного от объектов понятия.

Нельзя сказать, что объекты обмениваются сообщениями, если сообщения — это тоже объекты. Получается, объекты обмениваются объектами
Попробуем решить задачку.
а точнее не обмениваются, потому что ответное сообщение невозможно отправить тому, кто прислал входящее.
Ложное высказывание. Например здесь
BackTalker>>talkBack
	^ thisContext sender printString
экземпляр BackTalker-а получая сообщение talkBack, посылает сообщение отправителю — обмен сообщениями? Обмен! Не хочется тратить время на (не относящееся к теме) расписывание реализации объекта, который будет обрабатывать сообщения асинхронно и возвращать ответ через посылку «ответного» сообщения, примерно как в Erlang-е — очевидно это не очень сложно реализовать на Smalltalk. …Но это мало отношения имеет к моему вопросу.
Короче, бардак: нет ни обмена сообщениями,
Нет обязательного обмена сообщениями — как и в Erlang-е, кстати ;)
ни самих сообщений, как отдельного от объектов понятия.
Ага, и нет зайцев, как отдельного от животных понятия? А в Erlang-е нет понятия сообщения как отдельного от понятия валидный терм (т.е. от понятия «данные»). Бардак!!! ;)

И, наконец, я в очередной раз (даже мое занудство уже начинает заканчиваться) вынужден возвращать нас к исходному вопросу: мы не обсуждаем обмен сообщениями, вопрос был про сами сообщения.
экземпляр BackTalker-а получая сообщение talkBack, посылает сообщение отправителю — обмен сообщениями? Обмен!

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


Нет обязательного обмена сообщениями — как и в Erlang-е, кстати ;)

Что так? В Erlang он вполне себе обязателен на уровне акторов, никакого другого пути кроме обмена сообщениями в нём просто нет.


Ага, и нет зайцев, как отдельного от животных понятия?

Ну, допустим, зайца, не являющегося животным, найти можно: плюшевого, нарисованного и т.п.


А в Erlang-е нет понятия сообщения как отдельного от понятия валидный терм (т.е. от понятия «данные»). Бардак!!! ;)

Это как раз порядок, есть акторы, а есть данные. Акторы могут обмениваться данными. Всё чётко и по делу. Акторы не являются данными, а данные не являются акторами.

Если вы будете все результаты вычислений…
А мне не надо все: асинхронный обмен сообщениями требуется далеко не всегда.
Это как раз порядок, есть акторы, а есть данные. Акторы могут обмениваться данными. /…/ Акторы не являются данными, а данные не являются акторами.
То есть, в Erlang нет сообщений («как отдельного от объектов данных понятия). Соответственно, ни о каком обмене сообщений и речи нет. Далее напрашивается вывод, что из любого языка (даже из Prolog) можно сделать плохой Smalltalk. ;)
>Нет обязательного обмена сообщениями — как и в Erlang-е, кстати ;)
Что так? В Erlang он вполне себе обязателен на уровне акторов, никакого другого пути кроме обмена сообщениями в нём просто нет.
Да мне тут много раз уже зачем-то объясняли, что обрабатывать сообщения в Erlang-е не обязательно. По этой причине (а так же нескольки другим возможным причинам) ответа на сообщение может не быть. То есть, обмен сообщениями не обязателен. Наконец, я же могу на Erlang-е и без акторов обойтись?

Да мне тут много раз уже зачем-то объясняли, что обрабатывать сообщения в Erlang-е не обязательно. По этой причине (а так же нескольки другим возможным причинам) ответа на сообщение может не быть

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

Да, содержимое сообщения — это просто данные. Но чтобы его отправить нужно ещё выбрать способ отправки и получателя. Итого, данные, отправляемые адресату выбранным способом, — это сообщение. Пока данные никому не отправляются — это не сообщение. Этого достаточно чтобы выделить отдельный концепт.


Наконец, я же могу на Erlang-е и без акторов обойтись?

В том то и вся прелесть, что не можете. Всё есть акторы и ничего вне акторов не существует.

Этого достаточно чтобы выделить отдельный концепт.
Вот мы и выяснили, что сообщения таки в Smalltalk-е есть: выделили отдельный «концепт», более того, описали его на том же Smalltalk-е. Кстати, а на Erlang-е этот самый концепт можно описать? ;)
Всё есть акторы и ничего вне акторов не существует.
А как же выражения? А как же данные? А как же функции? А как же сообщения?

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

Они невозможны вне акторов.
Поясню свою мысль, надеясь что мы в очередной раз не уйдем куда-то в сторону.

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

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

Я могу здесь ошибаться. Если это так, и обсуждение вопроса о «чистоте» (или, кстати, как обозначить данное ответвление?) здесь важно, то я прошу сначала обосновать это, и лишь потом начинать баталии по сравнению подходов в этом аспекте.

выделили отдельный «концепт», более того, описали его на том же Smalltalk-е.

Ну смотрите, я по сути дал определение сообщения в Erlang:
Сообщение — данные, отправляемые адресату (актору) выбранным способом (обработка зависит от способа отправки, а не от пересылаемых данных).


Можете дать определение для Smalltalk? В принципе, наверно, стоило начать с определений, чтобы понять отличия.


этот самый обмен не обязателен для того, чтобы «настоящие» сообщения были: Erlang этот самый обмен на требует, но при этом имеет те самые «настоящие» сообщения.

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


Что касается внутреннего устройства акторов, это другой уровень — уровень реализации. Нет ничего страшного, что внутри клетки нет других клеток. Это позволяет прекрасно соблюдать SRP, Bounded Context и прочие важные архитектурные паттерны. У вас практически нет возможности напортачить со всем этим. В то же время, системы с обычным ООП повально страдают от несоблюдения этих принципов. И одна из основных причин почему так происходит — программист просто не понимает как правильно выделить классы. Вспоминается знаменитый холивар "строка печатает себя на принтере" vs "принтер печатает строку".


Понимание как правильно готовить ООП приходит с многолетним опытом, да и то не ко всем. А Erlang/Elixir с ходу даёт правильный подход из коробки. И уже набив шишки с популярным ООП, понимаешь насколько Армстронг был прав, говоря "любая отказоустойчивая архитектура в конце концов окажется похожей на Erlang".


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


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

Доброе…
Что не так с сообщениями в Smalltalk?

Если коротко, то «не так» там не с «сообщениями», но с тем, что называется словом messaging. «Сообщения» — как бы — есть, а вот «обмена сообщениями» — нет.

Грубо говоря, «ответ» — это не «сообщение» :-(

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

«Сообщения» — сами по себе — не могут быть ни синхронными, ни асинхронными. Процесс обмена сообщениями — может. И асинхронный процесс выгодней, т.к. имея его, синхронный получается «на автомате».

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

Бывают другие варианты? В Erlang/Elixir это не так? А как?

В Erlang — «всё вообще не так» :-) Там нормальный messaging.
Грубо говоря, «ответ» — это не «сообщение» :-(
Вот это — почти верно. Можно было бы «отмазаться», выдвинув версию, что возврат значения — это часть сообщения (процесса обмена сообщениями), так, собственно и определяется: сообщение можно послать объекту, объект возвращает некоторый объект как объект… Но возврат значения «забит» в синтаксис и сообщением, действительно не является.

На мой взгляд, это следствие заложенного в синтаксис «шаблона» посылки сообщения:
получатель сообщение.
Вот если бы сделать язык, где сообщение посылается «никому» (просто в окружающую среду — как в жизни), а кто хочет вылавливает и обрабатывает… но я об этом «мечтаю» уже несколько лет — никак не решусь облечь в слова :)

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

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

Почти?!
Можно было бы «отмазаться», выдвинув версию, что возврат значения — это часть сообщения (процесса обмена сообщениями),…

Нельзя… return, емнип, по спекам не относится к message passing.
На мой взгляд, это следствие заложенного в синтаксис «шаблона» посылки сообщения:

Это не следствие синтаксиса… это модель вычисления такая. Синтаксис — сам по себе — уже «следствие».
…Тем не менее, сообщения в Smalltalk-е есть, обмен сообщениями (с ответами на них) есть…

Еще раз… сообщения есть, а *обмена сообщениями* — в смысле *messeging* — в Smalltalk — нет. То, что в Smalltalk есть — это эдакий «RPC — вид сбоку».
… и почему их можно назвать «замаскированнными вызовами функций» для меня по-прежнему загадка. Если можете не коротко по этому поводу — было бы интересно таки услышать.

:-) Это «замаскированные вызовы функций» по той простой причине, что никакой другой *семантики* у сообщений Smalltalk нет. Это *всегда* и *только* вызов метода.

И это не синтаксис, опять же. Это модель вычисления у Smalltalk такая.

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

?! «Проблема» в том, что в результате — в лучшем случае — получается плохой Erlang :-)
то, как данное конкретное сообщение будет (и будет ли) обработано тем процессом, которому оно послано, определяется лишь той функцией, которую данный процесс в этот момент вычисляет
То есть, сообщение в Smalltalk-е — это замаскированный вызов метода, а сообщение в Erlang-е — это (как раз) замаскированнный вызов функции? (…ну, или замаскированное выражение?)

Нельзя… return, емнип, по спекам не относится к message passing.
«In Smalltalk, a message will always return a value» — это часть реакции объекта на сообщение. Как и в Erlang-е, в Smalltalk внутри обработчика сообщений (к моему сожалению) не все делается через сообщения. И, так же как и в Erlang, мы же не будем из-за этого утверждать, что messaging отсуствует?

Это не следствие синтаксиса…
Если вы не поняли мысль, поясню. Smalltalk позволяет в Object реализовать метод типа #return:, который будет осуществлять возврат значения отправителю исходного сообщения. То есть, возврат можно сделать сообщением, например
self return: 2 + 3.
Тогда messaging в Smalltalk-е появится?

Это не следствие синтаксиса… это модель вычисления такая.
Какая такая? Уточните пожалуйста :)

Еще раз… сообщения есть, а *обмена сообщениями* — в смысле *messeging* — в Smalltalk — нет. То, что в Smalltalk есть — это эдакий «RPC — вид сбоку».
Повторение — оно конечно мать ученья, но только в том случае, если там есть содержательная часть. У вас она пока отсутствует — больше смахивает на агитацию или самовнушение. …А после слов про RPC у меня закрались сомнения: вы же в курсе, как сообщения работают в Smalltalk-е, да? В каком отношении это напомнило вам RPC?

Это *всегда* и *только* вызов метода.
Какого именно метода, можете ответить?

Это «замаскированные вызовы функций» по той простой причине, что никакой другой *семантики* у сообщений Smalltalk нет. Это *всегда* и *только* вызов метода. … А в Erlang — сообщение это «голые» данные, и только. Какую-либо семантику они (эти данные) обретают лишь в контексте конкретной ф-ции.
Сообщение в Smalltalk-е — это «голый» объект, семантику он получает только в контексте конкретного объекта. В чем разница?

«Проблема» в том, что в результате — в лучшем случае — получается плохой Erlang :-)
О, опять агитация? А может быть проблема в том, что должно хватать разума и опыта понимать, что не существует просто лучшего решения. Даже такого прекрасного, как Эрланг с акторами. Как у вас с этим?
То есть, сообщение в Smalltalk-е — это замаскированный вызов метода, а сообщение в Erlang-е — это (как раз) замаскированнный вызов функции? (…ну, или замаскированное выражение?)

Послать сообщение в Erlang — означает ровно одно. Передать данные. И всё. Ничего «замаскированного» там нет… ни функций, ни выражений.

Т.е. послать сообщение x процессу A — *буквально* — означает только то, что если процесс A в данный момент существует, в его mailbox будет добавлено сообщение x. И ничего более. *Если* (*когда*) процесс А будет вычислять функцию, в которой есть receive expression, и *если* под этот receive попадет сообщение x, то это — действительно — может привести к вычислению какой-то отдельной функции… а может и не привести.

Но это вообще никак не зависит от *сообщения x*, а только лишь от той функции, в которой произойдет редукция такого receive.

«In Smalltalk, a message will always return a value» — это часть реакции объекта на сообщение. Как и в Erlang-е, в Smalltalk внутри обработчика сообщений (к моему сожалению) не все делается через сообщения. И, так же как и в Erlang, мы же не будем из-за этого утверждать, что messaging отсуствует?

Я, к сожалению, перестаю вас понимать. Причем тут вообще «реакция объекта на»?! Речь о том, что *результат* «реакции объекта» — т.н. return — это не message send, в терминах Smalltalk. Только и всего.

Причем это *явно* отражено во всех спеках, которые я помню.

Если вы не поняли мысль, поясню. Smalltalk позволяет в Object реализовать метод типа #return:, который будет осуществлять возврат значения отправителю исходного сообщения. То есть, возврат можно сделать сообщением, например self return: 2 + 3.
Тогда messaging в Smalltalk-е появится?

:-) Это вы, похоже, не понимаете о чем речь. Речь не о том, что *тип* return value не может быть «сообщением». Речь о том, что return это не message send expression. Вот и все.
% Это send expression 
A ! {self(), hello},
...
% А это receive expression
receive
  {Sender, Message} ->
    %А вот это тот самый return, о котором речь... в Erlang - внезапно - это send expression.
    Sender ! Message
end,

Вот об этом речь. О том, что «результат» *явно* отправляется. Механизм одинаковый, что в ту, что в обратную сторону. А не о том, есть return value или нет, часть это «реакции» или нет.

Какая такая? Уточните пожалуйста :)

Computational Model of Smalltalk Execution
A message send causes execution of the currently active method to be temporarily suspended and for program execution to continue starting with the first expression of another method. A message send directs a message to an object. The object is called the receiver of the message. A message consists of a method selector and a set of arguments. Each argument is a reference to an object. When an object receives a message, the method selector of the message is used to select the method from the object's behavior that corresponds to the selector. The method becomes the new locus of execution. Special processing takes place if the receiver's behavior does not include a method corresponding to the message's method selector.

A return terminates execution of a method and causes execution to resume within the method that executed the message send that activated the method containing the return. Execution continues immediately following the message send expression. The return provides a value (an object reference) that becomes the value of the message send.

Это из ANSI Smalltalk… для 80-го (внезапно, оказывается я еще помню байткоды его return'ов :-)) можете сами поискать, если так интересно.

А после слов про RPC у меня закрались сомнения: вы же в курсе, как сообщения работают в Smalltalk-е, да? В каком отношении это напомнило вам RPC?

:-) Я-то «в курсе». RPC — в том смысле — что, все «танцы» с сообщениями в Smalltalk сводятся исключительно к request–response протоколу.

Какого именно метода, можете ответить?

Вы серьезно не понимаете, что важно не «какого именно»?! Важно то, что это — как ни крути — всего лишь вызов *какого-то* метода. Так Smalltalk устроен.

Сообщение в Smalltalk-е — это «голый» объект, семантику он получает только в контексте конкретного объекта. В чем разница?

Я вот понять не могу… вы меня троллить чтоль пытаетесь? :-) Начнем с того, что сообщение в Smalltack это не «голый» объект. А вполне себе специальный. Имеет определенную структуру. В нем (в сообщении), в обязательном порядке, есть, например, т.н. message selector. *Зачем* он нужен надо объяснять? :-)

Собственно, это и означает наличие у сообщений Smalltalk семантики «вызова функции».

О, опять агитация?

:-) На всякий… про «плохой Erlang» — это цитата, практически.
Я вот понять не могу… вы меня троллить чтоль пытаетесь? :-)
Разумеется нет, я лишь пытался выяснить, на каком уровне идет дискуссия. И он меня вполне устраивает. Так что продолжаем? ;)

Насчет Erlang
Послать сообщение в Erlang — означает ровно одно. Передать данные. И всё. Ничего «замаскированного» там нет… ни функций, ни выражений.

в его mailbox будет добавлено сообщение x

будет вычислять функцию, в которой есть receive expression
, и *если* под этот receive попадет сообщение x
Не понимаю… вы ходите сказать, что поиск процесса по ID и помещение сообщения в его почтовый ящик, как и сопоставление сообщений из почтового ящика с образцом и выполнение соответствующих действий происходит неким магическим образом? Или же за этим скрывается что-то более банальное типа вызова функци или примитива ВМ… или, может быть, кода, вставленного компилятором?

…А к обсуждению Smalltalk предлагаю вернуться после того, как договоримся о терминах на примере Erlang, если вы не против?

Или же за этим скрывается что-то более банальное типа вызова функци или примитива ВМ… или, может быть, кода, вставленного компилятором?

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

Нет. Я не хочу сказать, что это происходит «неким магическим образом». Я вообще не понимаю, к чему тут этот пассаж, что именно вы пытаетесь таким образом узнать?
Что ж тут непонятного? Я хочу узнать, каким образом реализован механизм сообщений в Erlang.
В этом случае, могу порекомендовать обратиться к замечательной работе Эрика Стенмана… к т.н. BEAM Book

Ко всему прочему, там подробно есть и про «механизм сообщений».
Ок, слив засчитан :) На самом деле большое спасибо за ссылку на книгу — не знал о ее существовании.

В параграфе «The Process of Sending a Message to a Process» описана процедура посылки сообщения из одного процесса в другой — отсюда можно сделать вывод: в Erlang не настоящие сообщения, а лишь замаскированные процедуры. Все верно? ;)
в Erlang не настоящие сообщения, а лишь замаскированные процедуры. Все верно? ;)

:-))) Так-то — да… только небольшая поправка. Не «замаскированные процедуры», а «замаскированная процедура». Насколько уж она «замаскированная» — вопрос, имхо, религиозный. Но, она одна… и — что, на самом деле, гораздо более важно — абсолютно, вот просто никак вообще, не зависит от посылаемого сообщения.

И теперь вам только осталось стряхнуть пыль с какого-нибудь «Голберга и Робсона» и попытаться найти аналогичную процедуру в Smalltalk :-)
Зачем же откуда-то стряхивать пыль? «Процедура» описана стопиццот раз и до сих пор вполне успешно работает в различных современных реализация Smalltalk. Вы же ее и сами знаете, разве нет?

По селектору сообщения ищется метод в классе получателя; нашли — выполнили, не нашли — ищем в суперклассе… Дошли до корневого объекта и не нашли — отправили получателю doesNotUnderstand: с непонятым сообщением в качестве аргумента.

Так что? Сходимся на том, что в Smalltalk-е сообщения не менее настоящие, чем в Erlang-е? Или что в Erlang-е не менее замаскированные вызовы функций (вне-Erlang-овских), чем в Smalltalk-е?
По селектору сообщения ищется метод в классе получателя; нашли — выполнили, не нашли — ищем в суперклассе… Дошли до корневого объекта и не нашли — отправили получателю doesNotUnderstand: с непонятым сообщением в качестве аргумента.

Я, признаться, несколько удивлен… я же правильно понимаю, что вы на полном серьезе считаете вышеописанное аналогом того, что вы — надеюсь — прочитали в BEAM Book?! Прочитали же?

Я же не просто так просил: «попытаться найти». Я, конечно, предполагал, что свои поиски вы начнете с message send. Но я так же надеялся, что вы быстро увидите, что никаких аналогов там и близко нет. И будете «копать» дальше …

Видимо, с моей стороны, это была не очень удачной идей. Поэтому, попробуем еще раз :-)

Дело в том, что в Erlang — как это не удивительно — есть аналог вышеописанной вами «процедуры» Smalltalk. Только этот аналог не имеет никакого отношения ни к send, ни к receive expression. Он не про сообщения вообще.

Это т.н. «внешний вызов функции» (external call to the function). Т.е. когда какая-либо функция модуля вызывается «из вне», в Erlang происходит ровно та же «магия» что и в Smalltalk. Конечно, тут нет, в явном виде, message selector’а — есть связка name/arity; нет message-to-method словаря класса — вместо него export table модуля; нет иерархии «классов» — есть иерархия function clause; нет «doesNotUnderstand» — есть badarity и badmatch.

Но, если вы озаботитесь, и прочитаете про устройство VM Erlang, то увидите практически полную аналогию между call_ext VM Erlang и sendSelector VM Smalltalk. Я, на всякий случай, еще раз уточню — речь исключительно про «внешние» вызовы. «Локальные» в Erlang работают по-другому.

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

Вот и все.

Так что? Сходимся на том, что в Smalltalk-е сообщения не менее настоящие, чем в Erlang-е? Или что в Erlang-е не менее замаскированные вызовы функций (вне-Erlang-овских), чем в Smalltalk-е?

:-) Я таки питаю слабую надежду, что выше смог вам хоть что-то объяснить.

Тем не менее, если вы сможете показать мне *безусловную* связь сообщений в Erlang с диспетчеризацией вызовов (как вариант, показать, что «сообщения» Smalltalk такой связи не имеют) — я буду готов с вами согласиться :-)
Я, признаться, несколько удивлен… я же правильно понимаю, что вы на полном серьезе считаете вышеописанное аналогом того, что вы — надеюсь — прочитали в BEAM Book?! Прочитали же?
Разумеется прочитал! И вот я не удивлен: я ожидал, что вы меня с энтузиазмом потащите в дебри виртуальных машин. Но вы же — я очччччень на это надеюсь — не будете отождествлять понятия, их воплощение в синтаксисе языка и реализацию виртуальной машины? До BEAM у Erlang-а были другие виртуалки? Были времена, когда и виртуалки не было, не так ли? А Erlang был? Или с каждой новой VM (или с каждой новой версией VM) мы получаем новый язык? А каждый новый язык заставляет нас менять смысл понятий, на которых он базируется?

Описанная мной процедура является базовой — независимо от реализации Smalltalk (даже если внезапно начать говорить, что это и не Smalltalk вроде как, а, например, Pharo) она будет так или иначе реализована (частично в самой среде Smalltalk, частично за ее пределами — в виртуальной машине). И суть этой процедуры — связать «пожелания отправителя» с некоторым кодом в объекте. А Erlang связывает сообщение с кодом в акторе. В Smalltalk-е «единицей» кода является метод, в Erlang-е (если не ошибаюсь) — выражение. Соответственно, Smalltalk связывает сообщение с методом, Erlang — с выражением. Главное здесь (с моей точки зрения) — в чем заключается смысл понятия «сообщение», и в чем состоит очевидная (для меня) аналогия — это именно позднее связывание (другими словами, отказ от априорного знания о том, какой именно код будет выполнен — объект/актор «сам решает», как среагировать).
Дело в том, что в Erlang — как это не удивительно — есть аналог вышеописанной вами «процедуры» Smalltalk. /…/ Это т.н. «внешний вызов функции» (external call to the function).
При всем моем искреннем уважении к вашим глубоким знаниям внутреннего устройства различных (как я подозреваю) виртуальных машин, ваше подробное описание механизма позднего связывания для внешних функций в Erlang-е мало помогает разобраться с исходным вопросом и найти ошибку в моем понимании понятия «настоящего» сообщения (если она там есть). У меня создается впечатление, что вы стараетесь просто избежать прямого сравнения… Хотя кому, как ни вам (судя по всему, хорошо знакомому и с той, и с другой стороной медали) надо просто взять и понятным языком объяснить, что такое «истинное» сообщение (на уровне понятия) и (на уровне языка, а может быть и с помощью примеров) наглядно это продемонстрировать. Просто пока слова о «вырождении» сообщений в «динамическую диспетчеризацию» пока остаются лишь словами. Еще раз повторю свою мысль: то, что в Erlang-е связывание сообщений с выполняемыми для их обработки операциями выполняется некоторым определенным способом, еще не означает, что все другие способы тут же невилируют само понятие «сообщение». По крайней мере, я пока не в состоянии понять это относительно Smalltalk-овской трактовки.
Поэтому — лично для меня — нет ничего удивительного в «негодовании» Армстронга (и Кея, если уж на то пошло) по поводу «обмена сообщениями» в Smalltalk.
Можно ссылочку на негодование Кэя по этому поводу? Только, пожалуйста, пусть это будет не цитата его письма 2003 года в сквиковское сообщество, где он объясняет, что настоящим ядром Smalltalk/Squeak являются сообщения — я с ним знаком, там много интересного и полезного, но многое при этом допускает двойную трактовку (и я не вижу там негодования по поводу того, как сообщения реализованы в Smalltalk — оно больше об отношении к Smalltalk-у как данности, о нежелании развивать уже заложенные там и вносить/воплощать новые идеи). Хотелось бы чего-то более однозначного, по типу «да, мы хотели сделать и сделали Smalltalk на сообщениях, но мы изначально неверно понимали что такое сообщение, так что надо было сделать так-то и так-то».
Я таки питаю слабую надежду, что выше смог вам хоть что-то объяснить.
Я честно пытаюсь найти ответы на свои вопросы и разрешить свои сомнения с вашей помощью, но пока — увы! — вынужден констатировать, что ваших усилий недостаточно :) …Хотя данная дискуссия — говорю это вполне серьезно — для меня весьма полезна, заставляет продумывать и пере-продумывать многие важные вещи.

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

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

А Erlang связывает сообщение с кодом в акторе.
Лишь *позволяет* связать. Это важно.

В Smalltalk-е «единицей» кода является метод, в Erlang-е (если не ошибаюсь) — выражение.

?! Что есть «единица кода»?

Главное здесь (с моей точки зрения) — в чем заключается смысл понятия «сообщение»…

Так уже дайте свое определение этому понятию. Мы его обсудим.

…, и в чем состоит очевидная (для меня) аналогия — это именно позднее связывание (другими словами, отказ от априорного знания о том, какой именно код будет выполнен — объект/актор «сам решает», как среагировать).

А причем тут, я извиняюсь, сообщения?! Существует множество систем (и Erlang, кстати, в том числе), в которых late-binding прекрасно реализуется без них.

Можно ссылочку на негодование Кэя по этому поводу?

Поищу, конечно. Он достаточно часто сетует на то, что messaging в Smalltalk так и не был «доведен до ума».

Хотелось бы чего-то более однозначного, по типу «да, мы хотели сделать и сделали Smalltalk на сообщениях, но мы изначально неверно понимали что такое сообщение, так что надо было сделать так-то и так-то».

Это вы от Алана такое хотите услышать?! :-)))
Вообще-то, буду… т.к. не очень себе представляю, каким образом можно рассматривать системы, базирующиеся на RTS, в отрыве от этих самых RTS. Хотя бы исходя из того, что для одной и той же RTS может быть больше одного «синтаксиса».
Вы, когда вводите сокращение, расшифровывайте его, пожалуйста, а то приходится гадать, о чем речь (Run-Time System? ReTurn from Subroutine?). И, кстати, я так и не понял вашу мысль.
Лишь *позволяет* связать. Это важно.
Если это важно, почему бы сразу не пояснить, почему?
Так уже дайте свое определение этому понятию. Мы его обсудим.
Я его обязательно дам — уже начинаю подводить (промежуточные?) итоги данного обсуждения… Но вообще-то я-то рассчитывал, что люди, которые так рьяно поддерживают тезис о том, что где-то сообщения «ненастоящие», а где-то «настоящие», способны расшифровать это понятие, не скатившись (как по моим ощущениям пока и получается) к банальному «вот, что у нас — это правильно, а все остальное — нет»).
А причем тут, я извиняюсь, сообщения?! Существует множество систем (и Erlang, кстати, в том числе), в которых late-binding прекрасно реализуется без них.
Я поясню чуть позже — как раз когда попытаюсь резюмировать. Можем пока оставить данный вопрос «подвешенным»?
Это вы от Алана такое хотите услышать?! :-)))
Разумеется. Если человеконенавистничеств, как вы выразились, «негодует» по поводу реализации центрального (по его же задумке) понятия в своем детище, от него можно ожидать какого-то конструктива по этому поводу, нет?
Вы, когда вводите сокращение, расшифровывайте его, пожалуйста, а то приходится гадать, о чем речь (Run-Time System? ReTurn from Subroutine?).

?! Runtime System, конечно. Не предполагал даже, что после BEAM Book термин вам не знаком.

И, кстати, я так и не понял вашу мысль.
Может быть больше одного языка («синтаксиса») для одной и той же RTS. Вы — как я понимаю — предлагаете рассматривать исключительно синтаксис. Ну представьте себе какой-нибудь, гипотетический, Gossip для VM Smalltalk, в котором вместо
x at: s put: k
будет, например,
x.at(s).put(k)

И мы начнем рассуждать о том, что в Smalltalk «сообщения» есть, а в этом Gossip — нет?!

Если — с вашей точки зрения — «сообщения» Smalltalk можно свести исключительно к синтаксису, то они — тем более — «не настоящие» :-)

Я поясню чуть позже — как раз когда попытаюсь резюмировать. Можем пока оставить данный вопрос «подвешенным»?

Подожду, конечно. Интересно же :-)
Может быть больше одного языка («синтаксиса») для одной и той же RTS.
Несомненно.
Вы — как я понимаю — предлагаете рассматривать исключительно синтаксис.
Разумеется нет, меня вообще интересует концептуальный уровень, само понятие «сообщение». Пока что получается, что сообщения в Smalltalk-овской трактовке по мнению «Erlang-овцев» являются ненастоящими только потому, что они не такие как в Erlang-е. Нюансов выяснилось много и весьма интересных, но текущий итог примерно такой. С моей точки зрения это не очень конструктивно, изначально я рассчитывал на что-то более весомое.
Чуть не забыл…
Если это важно, почему бы сразу не пояснить, почему?
Важно для понимания разницы.

VM Smalltalk — в любом случае — превратит message send в вызов метода… пусть даже это и будет doesNotUnderstand. Т.е. вам *гарантируется* хоть какая-то обработка в прикладном коде.

В VM Erlang send expression *всегда* успешен. Даже если процесс, которому вы посылаете сообщение, не существует — никакой ошибки вы не получите. А если такой процесс таки существует, у вас нет никаких гарантий того, что ваше сообщение будет хоть когда-то обработано. Так что никакой обработки сообщений в прикладном коде VM Erlang вам не гарантирует.
Важно для понимания разницы.
Да эта разница и так понятна. Меня интересует, что важно для того, чтобы сообщения были «настоящими».
Меня интересует, что важно для того, чтобы сообщения были «настоящими».
Чтобы они были не про «вызовы методов», а про передачу данных. Хотя… предположу, что мы сейчас внезапно выясним, что, например, и UPD датаграмма — это «для того чтобы попросить получателя выполнить некоторую операцию» :-)
Чтобы они были не про «вызовы методов», а про передачу данных.
Вызов метода — это лишь конечный этап доставки сообщений способом, принятом в Smalltalk. Вы же не будете утверждать, что с помощью Smalltalk-овских сообщений я не могу передать данные? Впрочем, очевидно что просто «передачи данных» маловато, чтобы выделить сообщения. Можно же и ранне-связанным вызовом функции «передать данные»? Или такой вызов — это тоже передача сообщения? :)

И таки еще один важный вопрос: зачем же мы передаем данные?
Хотя… предположу, что мы сейчас внезапно выясним, что, например, и UPD датаграмма — это «для того чтобы попросить получателя выполнить некоторую операцию» :-)
Зачем передергивать? UDP — это способ доставки сообщения, датаграмма — это способ представления сообщений.
Вызов метода — это лишь конечный этап доставки сообщений способом, принятом в Smalltalk.
?! Ну так это и есть суть всех «претензий» к Smalltalk messaging.

Вы же не будете утверждать, что с помощью Smalltalk-овских сообщений я не могу передать данные?
Еще как буду :-) Передача данных и передача аргументов в ф-цию — это вещи ортогональные по своей сути.

Или такой вызов — это тоже передача сообщения? :)
Нет конечно.

Зачем передергивать? UDP — это способ доставки сообщения, датаграмма — это способ представления сообщений.
Тут вообще нет какого-либо «передергивания». Сообщение в Erlang это «upd датаграмма» и есть… и по сути, и — ну практически — по форме.
Можно ссылочку на негодование Кэя по этому поводу?

Есть цитата по поводу почему отказались от полноценных сообщений:


Take a look at the first implemented Smalltalk (-72). It implemented objects internally as a "receive the message" mechanism — a kind of quick parser — and didn't have dedicated selectors. (You can find "The Early History of Smalltalk" via Google to see more.)
This made the first Smalltalk "automatically extensible" in the dimensions of form, meaning, and pragmatics.

When Xerox didn't come through with a replacement for the Alto we (and others at Parc) had to optimize for the next phases, and this led to the compromise of Smalltalk-76 (and the succeeding Smalltalks). Dan Ingalls chose the most common patterns that had proved useful and made a fixed syntax that still allowed some extension via keywords. This also eliminated an ambiguity problem, and the whole thing on the same machine was about 180 times faster.

В общем, в Smalltalk когда-то были полноценные сообщения:


In Smalltalk-72, a message send was just a "notify" to the receiver that there was a message, plus a reference to the whole message. The receiver did the actual work of looking at it, interpreting it, etc.

Но их выпилили из-за performance-проблем, а терминология осталась. Отсюда и вся путаница.

Прежде всего, огромное спасибо за эту цитату!
In Smalltalk-72, a message send was just a «notify» to the receiver that there was a message, plus a reference to the whole message. The receiver did the actual work of looking at it, interpreting it, etc.
Я надеюсь, за alankay1 на ycombinator скрывается именно ОН? :) Просто сообщение, из которого она взята (а именно слова «What's fun is that every Smalltalk contained the tools to make their successors while still running themselves» …но подозреваю, что и вся дискуссия — я пока не успеваю с ней познакомиться) прямо вот про то, что довольно сильно занимает меня последние несколько лет. Не знаю, когда я ее нашел бы, если бы не ваша цитата.

По существу отвечу чуть позже — сейчас образовался некоторый цейтнот.
Я надеюсь, за alankay1 на ycombinator скрывается именно ОН? :)

Да, это ОН. И на Quora тоже он. Я реально рекомендую Вам задать какие-то из ваших вопросы ему лично (мне кажется, у вас есть несколько, которые давно беспокоят). Он уже года 3 как достаточно активно отвечает на этих двух ресурсах на все вопросы, адресованные ему.
И именно по этим его сообщениям можно понять, что он не в восторге от текущих реализаций Smalltalk. Разумеется, он не может негодовать на эту тему открыто. Каким бы ни вырос твой ребёнок, он всё равно твой и ты его всё равно любишь. Но между строк сквозит некое сожаление и мощная ностальгия по первым реализациям.


Кстати, есть ещё достаточно интересное видео:
https://www.youtube.com/watch?v=fhOHn9TClXY


What's fun is that every Smalltalk contained the tools to make their successors while still running themselves

Да, а дальше про то, что реанимировать настоящие сообщения в Smalltalk — могло бы быть увлекательной задачей для опытных смалтолкеров. Впрочем, думаю, задачка достаточно нетривиальная.

В очередной раз исходный вопрос сводится к призыву померяться… Давайте уже закроем это направление. Да, я тоже не в восторге от текущих реализаций Smalltalk. Еще в большем «невосторге» от того, что — за очень редким исключением — практически нет попыток что-либо принципиально изменить. И в моем понимании Smalltalk это не конкретная реализация ВМ и среды, а именно связка идей «сообщения и объекты» (и по возможности больше ничего), которая до сих пор не нашла достойного воплощения. В Smalltalk-сообществе все застряло на уровне 80-го года (ну, точнее все таки 87-го, но про Self сейчас совсем мало вспоминают). А учитывая, что в 72-м идея была даже мощнее, то все совсем плохо.

Но именно мои жалкие попытки понять, что со всем этим делать и вызвали исходный вопрос. Так что я в очередной раз предлагаю разбираться именно с ним.
Да, а дальше про то, что реанимировать настоящие сообщения в Smalltalk — могло бы быть увлекательной задачей для опытных смалтолкеров.
Вот, не надо опять «передергивать». Там нет ни слова про то, что в Smalltalk-72 были «настоящие» сообщения, а потом их «убили». Об этом разговор еще предстоит. А вот то, что механизм обработки сообщений в современных (начиная с 76-го) Smalltalk-ах неплохо бы пересмотреть — это да. Именно в эту сторону (хотя и с других исходных позиций, нежели Erlang-овские …впрочем, Erlang и акторы — само собой — тут тоже весьма полезны, иначе бы я не «разжигал») я и смотрю.

Я просто сократил "a message send was just a "notify" to the receiver that there was a message, plus a reference to the whole message. The receiver did the actual work of looking at it, interpreting it, etc." до "настоящие сообщения".
Вы же сами пытаетесь выяснить, что мы подразумеваем под "настоящими сообщениями" и почему в Smalltalk они ненастоящие. Наши объяснения Вас не устроили, поэтому я нашёл Вам ответ лично от Кэя.
Да, в Smalltalk-72 были сообщения, которые мы тут обозвали настоящими. Но эту идею не смогли реализовать приемлемо по скорости работы. Поэтому от неё отказались и заменили сообщения на "замаскированный вызов метода". А термин "сообщение" исторически остался от первых реализаций, в которых они были.


P.S. Если Вас даже объяснение от Кэя не устроит, тогда уже не знаю, что тут ещё дополнить. Не хочется перепечатывать уже написанное. По-моему, мы коллективными усилиями разжевали ответ на ваши исходные вопросы дальше некуда.

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

По поводу Smalltalk-72… Я хотел сам сначала получше изучить вопрос, но времени не хватает. Поэтому давайте так: вы уверены, что в Smalltalk-72 сообщения были полноценными именно в том смысле, который вы дружно вкладываете в этот термин? Или это только гипотеза? У вас есть более формальные (чем туманные намеки) подтверждения этому?

Если что, в сети есть мануал по Smalltalk-72 , есть вот такой обзор, есть работающий эмулятор. В мануале есть интересные намеки, которые вроде бы как близки к вашему утверждению, но явных и четких подтверждений я не нашел. Больше похоже, что сообщения просто интерпретировались (читались из потока символов, следующих за получателем)… Примерно то, как я это себе придумал, пытаясь преодолеть «нечистоту» современного Smalltalk-а (присваиания, возврат, некоторый синтаксический сахар — не сообщения). Но вроде бы это не подходит под вашу трактовку сообщений… Или подходит? :) Я пока не успеваю разобраться.
Ваши объяснения сводятся к утверждению «в Erlang-е сообщения полноценные, следовательно в других местах они ненастоящие».

Вовсе нет, такого вам никто не писал.


Они бы устроили, если бы где-то Кэй сказал, что начиная со Smalltalk-76 «сообщения уже не те»…

Я вам подскажу, в цитате выше есть слова "was" и "did", именно они в английском означают, что сейчас «сообщения уже не те».


Поэтому давайте так: вы уверены, что в Smalltalk-72 сообщения были полноценными именно в том смысле, который вы дружно вкладываете в этот термин?

Меня ещё и на свете то не было, когда Smalltalk-72 был в моде ))) Поэтому я тут полагаюсь только на слова Кэя. Зачем ему врать? Если там реально было так: "a message send was just a "notify" to the receiver that there was a message, plus a reference to the whole message. The receiver did the actual work of looking at it, interpreting it, etc.", то да — там были сообщения.


Эмулятор я видел, но им хрен разберёшься как пользоваться… В 70-е было модно что-ли программировать на символах, которые нельзя ввести в клавиатуры?

Я вам подскажу, в цитате выше есть слова «was» и «did», именно они в английском означают, что сейчас «сообщения уже не те».
Он говорит про 71–72 гг, какие еще слова он должен использовать?!? Прошу прощения, но это уже чушь какая.
Если там реально было так: «a message send was just a „notify“
Я в данный момент не могу точно понять, что скрывается под just a „notify“. Вы понимаете?
Эмулятор я видел, но им хрен разберёшься как пользоваться…
Есть мануал. Но если не хочется — не беда, я сам :)
Он говорит про 71–72 гг, какие еще слова он должен использовать?!? Прошу прощения, но это уже чушь какая.

Если бы сообщения в Smalltalk остались такими же по сей день, то ему не пришлось бы рассказывать про 72 год. Или он смог бы написать: "From the earliest versions of Smalltalk and till now a message send is ..." и так далее в Present Simple. Не согласны?

Изменилось еще много чего: объекты, классы, литералы… Изменились, но остались объектами, классами, литералами. Изменился синтаксис, но Smalltalk остался. Так что согласен: механизм обработки сообщений изменился, сообщения остались.

Так в этом то и вопрос, остались ли они сообщениями или стали замаскированными вызовами методов? Всё говорит в пользу второго. Но Вы упрямитесь и не хотите это признавать и готовы спорить хоть лично с Кэем, но почему-то тут, а не на Quora, где у него был бы шанс вам ответить.

Вы упрямитесь и не хотите это признавать и готовы спорить
Я уже много раз отмечал, что я не пытаюсь что-то оспорить или кому-либо что-то доказать. Я лишь пытаюсь выяснить, что такое «сообщение» в контексте ООП.
но почему-то тут, а не на Quora
Вопрос Кэю, раз уж вам так хочется получить одобрение вашей точки зрения от него, я задал. Только ответ в формате Quora, скорее всего, мало поможет. Если же c вашей стороны есть просто желание поставить точку в спорах (если вы их видите как некий поединок), то я не против:
«Вам все ясно, а мне надо подумать» (с) ;)
(Только что обнаружил, что один из моих ответов по какой-то причине не дошел.)
Вот другое объяснение, почему обработка сообщений в Smalltalk претерпела существенные изменения:
You will be interested to learn that the very first version of Smalltalk (Smalltalk-72) had a completely extensible syntax (in fact the writing of a class also automatically supplied the grammar). This worked very well, except… that too much freedom here leads to a Tower of Babel as far as other users are concerned. This has also been the experience with the few other really good extensible languages (like Ned Iron's IMP).

Extreme extensibility was removed in the next major design of Smalltalk (Smalltalk-76) in favor of a syntax that could read by anyone, regardless of how many classes had been defined… i.e., getting stronger meanings turned out to be more important in the end than making language structures fit the task.

That being said, I think this process went too far with Smalltalk-80, and needs more experimentation for the next generation, most of whom will be «occasional scriptors», and who need more readable (especially «gistable») code.
Это как раз

В этой цитате речь идёт только про синтаксис. На него в принципе без разницы. А в цитате выше речь была про то, что изменился механизм отправки сообщений и механизм приёма сообщений.


Хотя насчёт "too much freedom" я тоже не согласен. Когда получатель письма диктует отправителю в каком формате надо это письмо писать, это уже и не письмо, а заполнение анкеты. Так что ввод синтаксических ограничений тоже можно поставить в минус Smalltalk, но это не главное.

Или тут упор на «замаскированные вызовы функций»? Бывают другие варианты? В Erlang/Elixir это не так? А как?

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

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

Я просто хочу точно понять: данная фраза — просто не очень точная формулировка или за ней скрывается что-то действительно важное?
Чтение сообщения из почтового ящика — функция?

Нет, выражение.
Обработка очередного сообщения — функция?

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

да передача сообщения — вещь синхронная (надо дождаться ответа)
Ну, как бы и все :) В эрланге кинув сообщение можно ничего не ждать — все проблемы на принимающей стороне. А можно и ждать. Как захочется в общем.

Я просто хочу точно понять: данная фраза — просто не очень точная формулировка или за ней скрывается что-то действительно важное?

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

Я думаю, имелось в виду, что реализация обработки "сообщений" в Smalltalk ничем по сути не отличается от вызова метода в языках типа C++, Java и т.д. А в Erlang/Elixir она принципиально иначе реализована. Сообщение тут это не объект и не метод, а именно сообщение и ничто больше. Отправить его можно при желании кому угодно (любому актору), как и почтовый конверт любому адресату.

Я думаю, имелось в виду, что реализация обработки «сообщений» в Smalltalk ничем по сути не отличается от вызова метода в языках типа C++, Java и т.д.
Вот это «по сути» — можно раскрыть? Где коренится эта самая суть?

Может быть она в том, что в Smalltalk-е для связывания сообщения с кодом используется имя сообщения (селектор), а в Erlang/Elixir паттерн-матчинг (если я правильно понимаю)? …Но так ли это принципиально?

Сообщение тут это не объект и не метод, а именно сообщение и ничто больше.
Разве в Erlang сообщение — не «просто» терм? …А в Smalltalk — «просто» объект (но никак не метод) ;)

Отправить его можно при желании кому угодно (любому актору), как и почтовый конверт любому адресату.
…так же, как и в Smalltalk-е…

…Я так и не могу уловить эту самую вышеупомянутую суть.

…И еще раз (прошу прощения за занудство): в цитате написано про вызов функций. Это еще можно отнести, например, к C++: действительно, косвенный вызов через таблицу виртуальных методов можно назвать «замаскированными вызовом функции», но как можно таким образом охарактеризовать Smalltalk-овский подход — все равно не понимаю :)
Может быть она в том, что в Smalltalk-е для связывания сообщения с кодом используется имя сообщения (селектор), а в Erlang/Elixir паттерн-матчинг (если я правильно понимаю)?


Нет, это не так. Не уверен, что я смогу нормально объяснить, но всё же. В Erlang всё есть процессы (т.н. «грин-треды»), которые идентифицируются PID'ами. Каждый процесс исполняет какой-то произвольный код, с котором его запустили (я имею в виду, что никакого «типа» у процесса нет). Мейлбокс это свойство процесса, а не кода. Сообщения отправляются процессу (без деталей), зная его PID. Если код, выполняемый процессом не читает мейлбокс — значит, он его не читает. Всё. Можно долго отправлять такому процессу сообщения в одну сторону, пока мейлбокс не переполнится или процесс не закончится (выполнили весь код и вышли). Сообщения это просто данные. Можно читать, можно не читать. Можно читать и что-то делать, а можно читать и ничего не делать. Можно читать те, которые «нравятся», оставляя в очереди не подходящие. Отправка сообщений всегда односторонняя, у нее нет возвращаемого значения.

Я не очень много знаю о Smalltalk, но из того, что я прочитал — это вообще не похоже на Erlang.
Я не очень много знаю о Smalltalk, но из того, что я прочитал — это вообще не похоже на Erlang.
Если заменить слова «процесс» и «PID процесса» на «объект» и ориентироваться не на асинхронную, а синхронную обработку сообщений (делающую почтовый ящик ненужным, но очевидным образом допускающую и реализацию описанного асинхронного варианта), то все становится гораздо более похожим ;)
Если заменить слова «процесс» и «PID процесса» на «объект»
Нельзя заменить, у них разная семантика. Процесс — единица обработки/выполнения, объект — совокупность состояния и поведения. В Erlang объектом будет совокупность процесс + код, притом, при соблюдении некоторых дополнительных условий. Еще раз подчеркну — сообщения отправляются процессу, а не «объекту». Общего состояния у процессов нет.

ориентироваться не на асинхронную, а синхронную обработку сообщений (делающую почтовый ящик ненужным ...)
Опять нельзя. В рамках Erlang'овой модели у вас нет никаких гарантий, что что именно в этот момент, когда вы отправили сообщение, код, исполняемый процессом, будет этих самых сообщений ожидать. Собственно, нет гарантий, что процессом вообще будет исполнятся такой код, а это значит, что при синхронной модели (если б она была в Erlang) любая мелкая ошибка приведет к остановке всего — например, отправили сообщение процессу, код которого сообщения не читает -> ждем ответа бесконечно. Синхронная модель накладывает обязательства на получателя – это то, почему в Smalltalk есть протоколы. Еще раз повторюсь — в асинхронной модели Erlang на получателя не накладывается вообще никаких обязательств, именно потому, что модель асинхронная.

Асинхронная модель эмулируется, это правда. Producer и consumer, связанные очередью – довольно известный шаблон. Синхронная «объектная» модель эмулируется в Erlang, но тоже посылкой сообщений, со всеми вытекающими последствиями. Замечу, что вызов обычных функции в Erlang — синхронный, если что, но это не про акторы и процессы. Любая эмуляция остается эмуляцией, из под которой протечет настоящая модель.

В целом, то, что вы написали, сводится к «если все переделать, то станет похоже».
Процесс — единица обработки/выполнения, объект — совокупность состояния и поведения. … Общего состояния у процессов нет
Вы меня пугаете! :D Когда речь идет о том, что Erlang/Elixir поддерживают объектную парадигму лучше, чем некоторые «объектно-ориентированные» языки (и я с этим согласен), то проводите явную параллель между объектами и процессами (или акторами? или это одно и то же?) — и вдруг на попятную!?! :) У процессов разве нет локального состояния? В чем же такая принципиальная разница? Ориентация на concurrency и хорошая поддержка параллелизма — это фичи, а не принципиальная разница.

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

…Вторую часть вашего сообщения я, пожалуй, не буду комментировать, по крайней мере до тех пор, пока мы не начнем говорить об одном и том же :)
Я нигде не говорил ни про лучше, ни про хуже. Я вам пытаюсь объяснить то, как оно работает в Erlang, и какие сущности могут быть сопоставлены с понятием «объект» в других языках, в данном случае Smalltalk, и как работает механизм взаимодействия «объектов». А вы пытаетесь просто один к одному переложить понятия из одной экосистемы на другую – это не работает. Процесс это не объект, код это не объект и не класс. Стейт мейлбокса процесса не связан со стейтом кода, выполняемого процессом.

Акторная модель — это математическая модель прежде всего, для которой Erlang стал очень удобной платформой, позволяя ее реализовать посредством встроенных в платформу и язык фич, одна из которых — процессы с мейлбоксами. Но если вы создали процесс, и в качестве кода ему передали функцию, которая делает ничего — это не актор. Актор это то, что 1) принимает сообщения 2) посылает сообщения 3) создает другие акторы. Это концепция, в конце-то концов.

Ориентация на concurrency и хорошая поддержка параллелизма — это фичи, а не принципиальная разница.


Это очень, очень спорное заявление. Весь пример Erlang'а показывает, как введение определенных примитивов параллелизма в язык очень сильно меняет подход разработки.

Еще раз, не пытайтесь «смапить» сущности из одной парадигмы на другую 1 к 1, это очень часто не работает.
Я вам пытаюсь объяснить то, как оно работает в Erlang
Спасибо, но на том уровне, на каком вы мне объясняете — я в курсе :)
А вы пытаетесь просто один к одному переложить понятия из одной экосистемы на другую – это не работает.
Вы, похоже, неверно поняли, что хочу… В общем, еще раз спасибо за пояснения, освежить знания и услышать новые аспекты всегда полезно.
Вот чем Erlang-овская ООП действительно принципиально отличается от Smalltalk-овской, так это тем, что объектность в первом заканчивается на уровне… не знаю как назвать, но, грубо говоря, заканчивается гораздо раньше чем в Smalltalk-е :)
Вот это «по сути» — можно раскрыть? Где коренится эта самая суть?

В этой ветке уже многократно описали чем отличается пересылка сообщений в Erlang от вызова метода в какой-нибудь Java. А в чём тут отличие между Java и Smalltalk?
И там и там, получатель обязан иметь строго заданный тип (быть экземпляром класса, реализующего определённый интерфейс/протокол). И там и там, вызывающий объект не принимает сообщения от другого объекта, а ждёт return вызванного метода. И там и там объекты не изолированы на уровне виртуальной машины, как следствие вызов метода может уронить вызывающий объект, а точнее говоря всю программу.


Разве в Erlang сообщение — не «просто» терм? …А в Smalltalk — «просто» объект (но никак не метод) ;)

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

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

…Но какое отношение все это имеет к исходному вопросу?

В этой ветке уже многократно описали чем отличается пересылка сообщений в Erlang от вызова метода в какой-нибудь Java
У меня нет желания приплетать сюда еще и Java. Еще раз прошу посмотреть исходный вопрос и (а) ограничиться обсуждением Smalltalk и Erlang (б) с целью выяснения того, что такое настоящий messaging в противовес ненастоящему.

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

Вовсе необязательно. Можно ждать ответного сообщения.


В случае Smalltalk надо бы еще уточнить, что такое «вся программа».

Ну ok, в Smalltalk сама среда вряд ли упадёт, но остаться в состоянии, неспособном обрабатывать последующие запросы, вполне может.


В моем текущем (и не только моем) понимании сообщение отличается от вызова функции

Я думаю, непонимание цитаты началось именно с придирки к слову "функция", там очевидно имелся в виду "вызов метода". И про late binding (который Вы описали и который есть в куче ЯП) все знают, но это всё равно не обмен сообщениями. В Smalltalk у вызывающего объекта нет никакого способа получить ответ в виде сообщения. Как следствие, ни о каком обмене сообщениями говорить не приходится.

Я думаю, непонимание цитаты началось именно с придирки к слову «функция», там очевидно имелся в виду «вызов метода».
Нет, не принципиально. Я хочу понять, что такое «настоящие» сообщения в противовес «ненастоящим».
Можно ждать ответного сообщения …это всё равно не обмен сообщениями. В Smalltalk у вызывающего объекта нет никакого способа получить ответ в виде сообщения. Как следствие, ни о каком обмене сообщениями говорить не приходится.
Еще раз (или это в другой ветке было?): я могу реализовать средствами языка возврат значения через посылку сообщения; в этом случае что-то сразу поменяется?

Но хорошо, допустим обмен — это когда обязательно (зачем-то) нужно на сообщение отвечать сообщением. Но еще раз смотрим цитату (и мой вопрос): сами сообщения в Smalltalk остаются при этом не менее настоящими, чем в Erlang? или же в первом что-то не так именно с самими сообщениями? что именно?
… или же в первом что-то не так именно с самими сообщениями? что именно?

Поскольку я таки сдул пыль с «синей книги», то позволю себе процитировать прям вот самое её начало, практически:
A message is a request for an object to carry out one of its operations. A message specifies which operation is desired, but not how that operation should be carried out.

Вот это, собственно, и есть ответ на ваш вопрос :-) Именно это и есть, то самое «не так».
:D
А что именно не так-то? В Erlang-е сообщения посылаются с какой-то другой целью, совсем не для того чтобы попросить получателя выполнить некоторую операцию? Или сообщение в Erlang-е не связываются тем или иным способом образом с запрошенной операцией, не задавая при этом конкретную процедуру ее (операции) выполнения? Или же вас смущает терминология конца 70-х, ориентированная на тогдашнюю аудиторию? По мне, так тут дано определение понятия сообщения, независимо от способа его (сообщения) реализации.
Ну… нет. Посылающая сторона может, конечно, подразумевать своим сообщением что угодно, но что делать определяет получатель, поэтому одно и тоже сообщение одним и тем же получателем может быть обработано совершенно по разному в зависимости от фазы луны, или не обработано вовсе. То есть сообщение в эрланге в самом деле никак не связаны с «запрошенной операцией».
одно и тоже сообщение одним и тем же получателем может быть обработано совершенно по разному в зависимости от фазы луны, или не обработано вовсе
В Smalltalk-е все точно так же. Только «не обработано вовсе» в Smalltalk означает «может быть возвращено значение по умолчанию или выброшена исключительная ситуация, которую получатель может проигнорировать».
То есть сообщение в эрланге в самом деле никак не связаны с «запрошенной операцией».
Я, возможно (вероятность этого практически равна 1), чего-то не понимаю в Erlang-е, да и во всем окружающем мире, но относительно сообщений почему-то уверен, что они (в подавляющем большинстве случаев) посылаются с определенной целью и, как минимум, предполагают «ознакомление» получателя (да — по мере возможности, но все же) с ними. Я так же уверен, что для это — даже в волшебном Erlang-е — приходится выполнять определенные операции. И это будут операции получателя (объекта или актора).

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

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

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

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

Ведь, по идее, сделать это очень просто: привести пример сообщений, посылаемых с той самой «какой-то другой целью».

У меня есть сильное подозрение, что это не поможет, но извольте, мне не сложно. Сообщение {ok, 12345} — может быть послано любому процессу. Будет оно иметь для него смысл или не будет — полностью зависит от процесса-проучателя. Повторю — не от отправителя, а от получателя. Это сообщение будет корректным в случае если есть процессы для которых оно имеет смысл, оно будет корректным и в том случае, если таких процессов нет вообще.
Про обязательную и необязательную обработку уже надоело мусолить: это просто следствие асинхронности. Все это же можно реализовать поверх «обязательных» синхронных сообщений. Вопрос был не об этом!!!
У меня есть сильное подозрение, что это не поможет
Да, то что вы написали — не помогает никак, к сожалению. В Smalltalk-е тоже можно отправить любое сообщение (в т.ч. ok: 12345) любому объекту, имеет оно для него или хотя бы для одного объекта в системе — не важно… и т.д. и т.п. Но опять: вопрос не в этом. Если его вообще отправляют, значит это кому-нибудь нужно? ;)
Про обязательную и необязательную обработку уже надоело мусолить: это просто следствие асинхронности

Асинхронность обозначает, что можно не ждать ответа, а я говорю не про ответ, а обработку.
Обработка есть и в том, и в другом случае. Erlang при посылке сообщения помещает его в почтовый ящик адресата — это тоже обработка. Поскольку сообщение в Smalltalk-е посылается синхронно, система должна обеспечить возврат значения или выбросить исключительную ситуацию — поэтому она должна попробовать найти метод, который сможет обработать полученное сообщение.
Ну вы же сами говорите, что в одном случае вся работа заканчивается на пересылке сообщения, а в другом — обязателен этап обработки самого сообщения, ну! Пересылаются абстрактные данные, по сути просто байты не нуждающиеся в интерпретации, а обрабатываются байты, которые должны иметь какой-то смысл.
Я устал объяснять одно и то же, извините :)
Вот у меня ровно те же слова. Один-в-один.
А что именно не так-то? В Erlang-е сообщения посылаются с какой-то другой целью, совсем не для того чтобы попросить получателя выполнить некоторую операцию?

Вы, наверное, будете удивлены… но таки нет. В том смысле, что в Erlang вполне может быть процесс, для которого такое утверждение и имеет смысл. Но, в общем случае, в Erlang сообщения посылаются процессу действительно «с какой-то другой целью» :-)

Или сообщение в Erlang-е не связываются тем или иным способом образом с запрошенной операцией, не задавая при этом конкретную процедуру ее (операции) выполнения?

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

Или же вас смущает терминология конца 70-х, ориентированная на тогдашнюю аудиторию?

Даже так?! :-) Но, нет… меня не это «смущает». Меня больше «смущает», что вы упорно не видите разницы между системой, которая *безусловно* связывает *любое* сообщение с диспетчеризацией вызова, и системой, в которой такой связи нет.

Ну или видите, но считаете эту разницу не существенной :-)
Но, в общем случае, в Erlang сообщения посылаются процессу действительно «с какой-то другой целью»
Я на это утверждение ответил чуть выше, где прошу открыть мне тайну: с какой же еще целью, кроме выполнения каких-либо операций, посылаются сообщения?
Поскольку, в подавляющем большинстве никакой «запрошенной операции» просто нет
Надеюсь вы понимаете, что за словами «запрошенная операция» скрывается именно цель, с которой сообщение посылается, а не конкретный набор инструкций (как это было бы с вызовом функции/метода)?
Меня больше «смущает», что вы упорно не видите разницы между системой, которая *безусловно* связывает *любое* сообщение с диспетчеризацией вызова, и системой, в которой такой связи нет.
Ну или видите, но считаете эту разницу не существенной :-)
Я в другой ветке нашей дискуссии постарался объяснить свою позицию: Разница есть и на мой взгляд заключается она в реализации, при этом не затрагивая суть понятия «сообщение». Существенна эта разница или нет — зависит от того, существенна для чего. Я по-прежнему не вижу, как Smalltalk-овская реализация понятия «сообщение» делает сообщения «ненастоящими».
Я на это утверждение ответил чуть выше, где прошу открыть мне тайну: с какой же еще целью, кроме выполнения каких-либо операций, посылаются сообщения?

:-) В реальности, большинство процессов (утрирую, конечно… но, совсем немного) вычисляют, примерно, такое:
handle(From, Fun) -> From ! {ok, Fun()}.

Вы считаете, что сообщение {ok, X}, которое в конце своей работы пошлет «куда-то» такой процесс — это «чтобы попросить получателя выполнить некоторую операцию»? :-)

Разница есть и на мой взгляд заключается она в реализации, при этом не затрагивая суть понятия «сообщение».

Ну вот как только мы прочитаем ваше определение «сообщения», то можно будет и про «суть» поговорить.
Вы считаете, что сообщение {ok, X}, которое в конце своей работы пошлет «куда-то» такой процесс — это «чтобы попросить получателя выполнить некоторую операцию»? :-)
Разумеется! Более того, ваш пример очень хорошо иллюстрирует мою мысль. Ведь это сообщение посылается потому, что получатель заинтересован в анализе успешности выполнения запрошенной функции, не так ли?
Ну вот как только мы прочитаем ваше определение «сообщения», то можно будет и про «суть» поговорить.
Я уже выше написал, что ожидал от специалистов по языку с «настоящими» сообщениями его услышать. Не выйдет? :)
Ведь это сообщение посылается потому, что получатель заинтересован в анализе успешности выполнения запрошенной функции, не так ли?
Ну т.е. не «для того чтобы попросить получателя выполнить некоторую операцию»? Я ответил на ваш *первоначальный* вопрос?

Я сейчас не буду уточнять, что конкретно вы понимаете под «заинтересованностью» и «анализом». Просто, если вас «смущает» ok в кортеже, можете смело его убрать. Это абсолютно ничего не поменяет.
Ну т.е. не «для того чтобы попросить получателя выполнить некоторую операцию»?
То есть, именно для того! Чтобы получатель выполнил операцию по обработке результата.
Просто, если вас «смущает» ok в кортеже, можете смело его убрать. Это абсолютно ничего не поменяет.
Принципиально, разумеется, ничего не поменяется, но наличие этого ok в данном случае как раз обращает наше внимание на то, что мы готовим сообщение под получателя. Подготавливаем мы его именно потому, что мы (откуда-то) знаем, что операции по обработке будет нужен не только результат вычисления функции, но и этот статус. Разве нет?

Да не обязательно. Никто не заставляет как-то обрабатывать этот ответ. Этим сообщения и отличаются от вызова метода. Получатель может их игнорировать.


Ну, как веб-запрос вам возвращает статус, заголовки и тело ответа, но это вообще не значит, что любой клиент будет всё это как-то обрабатывать. Клиент может даже завершить свою работу до того, как сервер отправит ответ.

Никто не заставляет как-то обрабатывать этот ответ. Этим сообщения и отличаются от вызова метода. Получатель может их игнорировать.
Ну, мы на очередной круг заходим? Попробую кратко:
  1. Игнорировать можно пустым методом (в том числе и #doesNotUnderstand:
  2. Если п.1 не устраивает, то сообщения могут быть исключительно асинхронными? Но тогда термин «синхронное сообщение» было бы оксюмороном, а это, очевидно, не так.

Видимо, сообщения от «вызова методов» таки отличаются чем-то другим?

Что это вообще такое — «вызов метода»? Что этот термин означает и чем отличается от вызова функции?

…И кстати, все «не доходят руки» уточнить:
Получатель может их игнорировать.
Как часто мы хотим, чтобы получатель игнорировал полученные сообщения? Грубо говоря, это хорошо, если очень много посланных сообщений игнорируется?
Игнорировать можно пустым методом (в том числе и #doesNotUnderstand:

Это не игнорирование, а ничегонеделание при обработке. Так тоже можно, но это совсем другой вариант.


Как часто мы хотим, чтобы получатель игнорировал полученные сообщения? Грубо говоря, это хорошо, если очень много посланных сообщений игнорируется?

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


iex(1)> pid = spawn fn -> 1 + 2 end
#PID<0.134.0>
iex(2)> Process.alive?(pid)
false
iex(3)> GenServer.cast(pid, :message)
:ok
Но в целом, это ни хорошо, ни плохо, это просто нормально.
Создание бесполезной нагрузки на процессор и память — это нормально?

Можно подумать, что у вас в программах вся нагрузка на процессор полезная xD
Стабильность и отказоустойчивость важнее экономии на спичках.

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

Это не аналог исключений. Это основа для любой отказоустойчивой распределенной системы, обязательная часть её штатной работы (см. принцип Let It Crash).


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


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

Ну, я так и думал, что мысль не поймут (или не захотят понять). Все правильно (более-менее, не хочу спорить по мелочам). Просто есть и другие пути, как есть и другие сообщения. Когда будет возможность, я на других ветках сконцентрируюсь — там данный вопрос (в чуть ином аспекте, может быть) тоже обсуждается.
Чтобы получатель выполнил операцию по обработке результата.
1. «Получателя» может не быть;
2. «Получатель» может не обрабатывать сообщения вообще;
3. «Получатель» может не обрабатывать «такие» сообщения;
4. «Получатель» может не отличать «такие» сообщения от других.
и т.д. и т.п.

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

Разве нет?
Нет… это просто «рефлексы» и code style. Было бы:
From ! Fun().
— ничего бы не поменялось.
ничего бы не поменялось.
И в первом, и во втором случае «на той стороне» сидел бы один и тот же код и одинаково успешно работал бы?
И в первом, и во втором случае «на той стороне» сидел бы один и тот же код и одинаково успешно работал бы?
А в чем, собственно, проблема-то?! Очень может быть, что и «сидел бы один и тот же код».
Это, конечно же, не принципиально, просто интересно — я же Erlang не знаю практически. Как такой код будет выглядеть?
Я понимаю, что «когда в руке молоток ...»
В данном случае вы неправильно понимаете. Разумеется, все перечисленные ситуации я учитываю и сознаю, что вы пытаетесь понятие «сообщение» свести к (ни к чему не обязвающей) передаче «чистых данных». Но как ни крути, и в самом корне слова «сообщение» на русском, и в любой трактовке это понятия закладывается смысл. Смысл сообщения учитывается получателем при обработке, но и отправитель должен придать его при отправке.

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

Здесь я и вижу ту самую разницу между Эрланговскими и Smaltalkовскими сообщениями. Первый позволяет программисту полностью решать, как именно запихнуть «смысл» сообщения в это сообщение. Второй предлагает в качестве базового один конкретный способ. Из этого выводятся и все остальные отличия. Например в Smalltalk-е, раз решено смысл сообщения кодировать именем, то давайте внутри объекта группировать обработчики этих имен — структурировать их по смыслу. Получаем те самые ненавистные вам методы. Хорошо это или плохо, и что лучше — вопрос отдельный. Мой же вопрос заключается в том, действительно ли такая трактовка сообщений испортила их настолько, что они перестали быть сообщениями? До сих пор склоняюсь к отрицательному ответу на этот вопрос.
Но как ни крути, и в самом корне слова «сообщение» на русском, и в любой трактовке это понятия закладывается смысл.
?! Рискну вас удивить, но сообщение/message — вполне себе таки инженерный термин. И ваша «апелляция» к естественным языкам, в контексте данного обсуждения, вызывает у меня легкое недоумение.

Смысл сообщения учитывается получателем при обработке, но и отправитель должен придать его при отправке.
Что, по вашему, есть «смысл сообщения»?
Что, по вашему мнению, должен сделать «отправитель», чтобы придать «смысл» числу, скажем, пять. Число пять, может же быть «сообщением»? Или нет?

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

Если эта функция выполняет одну единственную «операцию», этот смысл «единственен», и все получаемые данные функция «потребляет» единым образом.
Что-то как-то подозрительно много новой «терминологии».
handle() ->
  receive
    {_, A} ->
      f(A);
    {_, A, _} ->
      f(A);
    [A|_] ->
      f(A);
    A ->
      f(A)
  end.
Сколько «операций» выполняет ф-ция handle? Каким образом эта ф-ция данные «потребляет»? В смысле, «единым образом» или нет?
handle() ->
  receive
    A ->
      f(A)
  end.
А теперь? Главное, не забыть, что f может же быть определена и, например, как:
f({_, A}) ->
  consume(A);
f({_,A,_}) ->
  consume(A);
f([A,|_]) ->
  consume(A);
f(A) ->
  consume(A).
На всякий случай, сразу уточню, что нам ничего не мешает вычислять f и в отдельном процессе. Причем, в «реальной жизни», так и происходит, в большинстве случаев.

Так что я как-то слабо понимаю, о чем вы пытаетесь сказать. К сожалению…

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

И тут вроде бы как есть всего два пути: либо мы сообщаем это через внешнее/глобальное(?) состояние, либо засовываем эту информацию в само сообщение.
Опять же… если на входе *данные* — их, для начала, надо как-то интерпретировать. А интерпретация данных — очевидно — не может определяться самими данными. Это, если хотите, ф-ция от.

Второй предлагает в качестве базового один конкретный способ.
Так в том-то и дело, что это не «базовый» это способ. Это *единственный* способ. Как бы мы не «приседали», нам не удастся лишить «сообщения» Smalltalk семантики function call. Они обладают ей без относительно какого-либо объекта. Это их перманентное свойство.

Кстати, какой-нибудь, пресловутый, doesNotUnderstand (да и вообще, т.н. «делегирование» aka «forwarding») как раз очень показателен, в этом смысле. Вот вроде есть у меня готовое «сообщение» аMessage. Я даже знаю кому его надо отправить: aReceiver. Но выясняется, что aMessage — а это, если хотите, и есть те самые «чистые данные» — не сообщение. И отправить его я не могу. Нет у aMessage нужной для этого семантики. :-)
?! Рискну вас удивить, но сообщение/message — вполне себе таки инженерный термин.
Что меня действительно бы удивило — если бы вы это (устраивающее вас) определение привели :) Но раз не привели, значит, не очень-то и нужно? Будем исходить из этого…
Что, по вашему, есть «смысл сообщения»?
Что, по вашему мнению, должен сделать «отправитель», чтобы придать «смысл» числу, скажем, пять. Число пять, может же быть «сообщением»? Или нет?
— Петька, приборы?
— Пять, Василий Иванович!
— Что пять?
— А что приборы?
Число пять может быть содержимым сообщения, если получатель «понимает» как проинтерпретировать эту пятерку, а отправитель знает, как получатель будет ее интерпретировать. Именно это «общее» знание я и называю «смыслом» сообщения.

…Кстати, послать сообщение 5 в Smalltalk-е тоже возможно:
(Message selector: 5) sendTo: 10.
Если вы таки про *интерпретацию* данных, то она — безусловно — на стороне «получателя».
Интерпретация — да, у получателя. Но не надо забывать, что сообщения посылаются не просто так, а с определенной целью/намереньем. А цель эта — у отправителя. Вот и получается, что «смысл» сообщения находится не в получателе, и не в отправителе, а «где-то между» (контекст?).
Что, по вашему мнению, должен сделать «отправитель», чтобы придать «смысл» числу, скажем, пять.
(Ура, мы добрались до сути!) Наверное, нужно как-то «договориться» об этом смысле — определить общий контекст? Вот, в Erlang-е это (как я понимаю) «отдали на откуп» программистам. В Smalltalk-е (судя по всему, начиная со Smalltalk-76) решили встроить «базовый» способ (известный человечеству и «обкатанный им» в течение тысячелетий): давать (сообщениям) имена. Отсюда логически «вытекает» и «базовая» обработка сообщений, и явное структурирование кода по тому же принципу на фрагменты, отвечающие за обработку конкретных сообщений — на методы.

Мне, кстати, тоже такое решение не особо нравится. Но сохранился ли принцип построения систем через посылку сообщений? По-моему, да. (Тут можно поднять еще вопрос о том, зачем вообще нужно от вызывов функций переходить к сообщениям, и показать, что эта задача успешно решается… но не уверен, что надо здесь и сейчас.)
Гораздо более важным (то, что мне кажется, вы упускаете), является тот факт, что одни и те же данные могут быть интерпретированы по разному. Даже одним и тем же «получателем».
Я понимаю, что это возможно в Erlang, но не понимаю почему это «важно».

(На оставшуюся часть я отвечу по мере возможности …и надобности)
… получатель «понимает» как проинтерпретировать эту пятерку, а отправитель знает, как получатель будет ее интерпретировать
А вот это уже сильно напоминает, то, что называется *протокол* :-)

…Кстати, послать сообщение 5 в Smalltalk-е тоже возможно:
(Message selector: 5) sendTo: 10.
При всем моем уважении, в двух представленных тут сообщениях, нет «сообщения 5».

Но не надо забывать, что сообщения посылаются не просто так, а с определенной целью/намереньем.
На второй круг пошли? :-)

Вот и получается, что «смысл» сообщения находится не в получателе, и не в отправителе, а «где-то между» (контекст?).
А мне вот очевидно, что у *сообщения* как раз и нет какого-то такого «смысла». Он — «смысл», в вашей интерпретации — безусловно, есть. У протокола, например. Но не у какого-то конкретного *сообщения*. Хотя бы исходя из того, что в протоколах (да даже системах), которые построены не на сообщениях, такой «смысл» тоже присутствует :-)

И, в любом случае, что именно вы хотите введением в топик этого самого «смысла» объяснить — мне, к сожалению, так и не стало понятно.

В Smalltalk-е (судя по всему, начиная со Smalltalk-76) решили встроить «базовый» способ (известный человечеству и «обкатанный им» в течение тысячелетий): давать (сообщениям) имена.
Дело же не в том, что у сообщений SmallTalk есть «имена». И даже не в том, что эти «имена» — это не данные. Дело именно в жесткой «склейке» передачи данных, и их обработки. Жесткой до такой степени, что, собственно, от передачи там ничего и не остается… и становится совершенно не понятно, чем такой message send *принципиально* отличается от function call.
При всем моем уважении, в двух представленных тут сообщениях, нет «сообщения 5».
Вы хотели послать 5? Я создал объект, представляющий сообщение «5», и послал его получателю.
А мне вот очевидно, что у *сообщения* как раз и нет какого-то такого «смысла». Он — «смысл», в вашей интерпретации — безусловно, есть. У протокола, например. Но не у какого-то конкретного *сообщения*. Хотя бы исходя из того, что в протоколах (да даже системах), которые построены не на сообщениях, такой «смысл» тоже присутствует :-)
То есть, поскольку данные тоже присутствуют даже в системах, которые построены не на сообщениях, нам должно быть очевидно, что их нет в сообщениях?

Каждая посылка сообщения выполняется с некоторой целью. Чтобы этой цели достичь, и отправитель, и получатель должны понимать смысл этого сообщения. Я не уверен, что смысл и протокол — одно и то же. Но не очень хочу обсуждать еще и это, не принципиально. Хотите, «запихните» «смысл» в «протокол» — тогда каждое сообщение будет получать свой смысл из него. В Smalltalk-е «смысл» закодирован в имени (селекторе сообщения).
И, в любом случае, что именно вы хотите введением в топик этого самого «смысла» объяснить — мне, к сожалению, так и не стало понятно.
Неужели так сложно? Вы согласились, что некий смысл есть (пусть и назвали его протоколом). Этот смысл может быть где-то, а может быть в самом сообщении. Первый выриант — Erlang, второй вариант — Smalltalk.
Дело именно в жесткой «склейке» передачи данных, и их обработки. Жесткой до такой степени, что, собственно, от передачи там ничего и не остается… и становится совершенно не понятно, чем такой message send *принципиально* отличается от function call.
Здесь мы вернулись в то место, где уже были (и, вроде бы, даже не раз) — смысла повторять пройденный путь не вижу.
Вы хотели послать 5? Я создал объект, представляющий сообщение «5», и послал его получателю.
Какое из двух *сообщений* seleсtor: 5 и sendTo: 10 есть «сообщение 5»? Причем — вы же, надеюсь, это понимаете — все эти «танцы» легко можно заменить на 10 perform: 5, и не создавать «объект, представляющий сообщение» (собственно, sendTo: у Message как раз в perform и «разворачивается», емнип). Вот только даже perfrom: 5 — это не «сообщение 5», это *сообщение* perfrom.

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

Каждая посылка сообщения выполняется с некоторой целью. Чтобы этой цели достичь, и отправитель, и получатель должны понимать смысл этого сообщения.
Я извиняюсь, но это вот прям очень похоже на утверждение о том, что для исполнения алгоритма необходима его понимать :-)

Что касается сообщений (и вообще данных), то единственная «цель», с которой они могут куда-то «посылаться» — это, очевидно, их обработка. И с этим, насколько я вижу, вообще никто не спорит. Спор вызывает ваше настойчивое желание показать/доказать, что тот способ, которым данное сообщение будет обработано (характер этой обработки, если хотите), это имманентное свойство самого сообщение (данных). Мне вот такой «постулат» кажется очень странным. Для меня очевидно другое… то, что с этим сообщением произойдет (и произойдет ли вообще) определяется исключительно «получателем».

В Smalltalk-е «смысл» закодирован в имени (селекторе сообщения).
Т.е. под «смыслом сообщения» вы таки понимаете лишь то, каким образом данное конкретное сообщение *должно* быть обработано «получателем»?

Вы согласились, что некий смысл есть (пусть и назвали его протоколом).
Это, скорее всего, уже не важно, но я не «смысл» назвал протоколом. Я сказал, что такой «смысл» есть у протокола. Но, не суть :-)

Этот смысл может быть где-то, а может быть в самом сообщении. Первый выриант — Erlang, второй вариант — Smalltalk.
Ну т.е. ответ на ваш изначальный вопрос можно сформулировать так: «настоящие» сообщения (в Erlang, например) это данные, сами по себе, лишенные какого-либо «смысла». Так?

Здесь мы вернулись в то место, где уже были (и, вроде бы, даже не раз) — смысла повторять пройденный путь не вижу.
Да и не надо «повторять» :-) Вы лучше просто подумайте вот ещё о чем. В Erlang, для того, чтобы вызвать какую-либо ф-цию, нет необходимости посылать какое-либо сообщение. При этом, результат вычисления ф-ции не зависит от того, в каком процессе она будет вычислена (хотя, на самом деле, это не всегда так… но, т.к. «словарь процесса» используется действительно очень редко, этим можно пренебречь). Ну т.е. — с т.з. результата обработки — нет разницы, будет эта ф-ция вычислена в «нашем» процессе, или в каком-то другом. Тем не менее, сообщения (как и процессы) в Erlang используются повсеместно. Может быть дело таки не в «вызовах ф-ций»? Может быть сообщения в Erlang — они про другое?
Кстати, какой-нибудь, пресловутый, doesNotUnderstand (да и вообще, т.н. «делегирование» aka «forwarding») как раз очень показателен, в этом смысле. Вот вроде есть у меня готовое «сообщение» аMessage. Я даже знаю кому его надо отправить: aReceiver. Но выясняется, что aMessage — а это, если хотите, и есть те самые «чистые данные» — не сообщение. И отправить его я не могу. Нет у aMessage нужной для этого семантики. :-)
Теперь я не понимаю. Что такое aMessage? Просто в принятых среди Smalltalk-еров соглашениях aMessage намекает, что там экземпляр Message, и с его отправкой нет проблем. Или вы сокрушаетесь, что не можете отправить произвольный объект как сообщение? Можете, просто для этого надо «объяснить» объекту, с какой целью вы хотите это сделать — дать имя сообщению. Требование, что у сообщения должно быть имя, превращает сообщение в не-сообщение?

…Только при чем тут #doesNotUnderstand?
Что такое aMessage?
Экземпляр Message, вестимо.

… экземпляр Message, и с его отправкой нет проблем.
С некоторых пор — условно — нет проблем с *делегированием* (через какой-нибудь perform). А вот с *отправкой* как раз проблемы… как были, так и остались. Как-то не работает оно без рефлексии :-) Вы же, надеюсь, в курсе, как работает тот же perform?

Или вы сокрушаетесь, что не можете отправить произвольный объект как сообщение?
Скорее уж, я «сокрушаюсь», что сообщение это не объект :-) Вот «всё есть объект», а сообщение — нет :-)

Требование, что у сообщения должно быть имя, превращает сообщение в не-сообщение?
Скорее, то, что это «имя» — *литерал*, а не выражение. То, что оно не может быть *вычислено*, если хотите.
С некоторых пор — условно — нет проблем с *делегированием* (через какой-нибудь perform). А вот с *отправкой* как раз проблемы… как были, так и остались. Как-то не работает оно без рефлексии :-) Вы же, надеюсь, в курсе, как работает тот же perform?
Вы постоянно общаетесь какими-то намеками, недосказанными мыслями, «тестируете» мою эрудицию и т.п., а троллем обзывают при этом меня… но ладно… Угадывать что вы там подразумеваете не буду, так что
  • отвечаю на поставленный вопрос:
    например, так
    Object >> perform: aSymbol
    	<reflective: #object:performMessageWith:>
    	<primitive: 83>
    	^ self perform: aSymbol withArguments: (Array new: 0)
  • …и напомню одну цитату:
    Объекты отвечают (или должны отвечать) на сообщения, и когда вы хотите что-то сделать – вы посылаете объекту сообщение, а уж как он обработает его — совершенно не важно.
Скорее уж, я «сокрушаюсь», что сообщение это не объект :-) Вот «всё есть объект», а сообщение — нет :-)
Утверждение неверное:
messageSent := GHObjectGhostStub new someMessage.
(messageSent isKindOf: Message) & (messageSent selector = #someMessage) & (messageSent isKindOf: Object).
выдает true. На всякий случай, чтобы не воспроизводить ваш стиль, поясняю: экземпляры GHObjectGhostStub возвращают полученные сообщения в качестве результата; первые два условия — для того чтобы показать, что это именно посланное сообщение; третье условие, разумеется, избыточно, но вы же настаиваете ;)
Скорее, то, что это «имя» — *литерал*, а не выражение. То, что оно не может быть *вычислено*, если хотите.
Опять ложное утверждение:
(((Message selector: ('evaluated','Message')) sendTo: (GHObjectGhostStub new)) selector) = #evaluatedMessage.
снова выдает true!
например, так
:-) А чего сразу было не «спуститься» до полного
Object >> perform: selector withArguments: argArray inSuperclass: lookupClass 
и показать нам тот самый «магический» message send?

Объекты отвечают (или должны отвечать) на сообщения, и когда вы хотите что-то сделать – вы посылаете объекту сообщение, а уж как он обработает его — совершенно не важно.
Так и покажите уже как *послать* объекту *такое* сообщение. Пока, все что мы видели, это — вполне конкретные — *сообщения* sendTo и perform.

экземпляры GHObjectGhostStub возвращают полученные сообщения в качестве результата
Он не это делает. *Сообщение* в SmallTalk нельзя *вернуть* «в качестве результата». Это by design так. Объекты класса Message — это не *сообщения* SmallTalk.

… снова выдает true!
Ещё бы. Вот только — среди аж трех *сообщений* — тут нет *сообщения* evaluated: 'Message'. Я просто напомню, что *сообщение* в SmallTalk это вполне конкретная вещь. И — скорее, к сожалению — к классу Message они не имеют никакого отношения. Ну, и чтобы вы меня опять не попрекали намеками", уточню: надо тут давать определение message send expression? Просто, других «мест», где в SmallTalk «живут» *сообщения* я лично — не знаю.
я могу реализовать средствами языка возврат значения через посылку сообщения; в этом случае что-то сразу поменяется?

Если у вас не будет никакого другого способа вернуть значение, то да — многое поменяется.


сами сообщения в Smalltalk остаются при этом не менее настоящими, чем в Erlang? или же в первом что-то не так именно с самими сообщениями? что именно?

В конечном итоге, в Smalltalk всё равно есть соответствие "сообщение — метод", кроме спец.исключения doesNotUnderstand. В Erlang все сообщения обрабатываются через стандартные behaviours, типа этого. Таким образом, приём сообщений и код реакции не связаны напрямую. Например, вы можете переименовать функцию, которая реализует реакцию на сообщение, но вся остальная программа об этом не узнает, не надо будет менять код отправки этого сообщения. И даже роль почтальона играет отдельный модуль


gen_server:call(pid_or_pname, message)
Если у вас не будет никакого другого способа вернуть значение, то да — многое поменяется.
Что именно? И почему это не поменяется, если будут другие способы вернуть значение? Например, как на это влияет возможност вызывать функцию, которая вернет значение другим способом?
В Erlang все сообщения обрабатываются через стандартные behaviours, типа этого. Таким образом, приём сообщений и код реакции не связаны напрямую.
В Smalltalk-е тоже прием сообщения и код реакции не связаны напрямую!
Например, вы можете переименовать функцию, которая реализует реакцию на сообщение, но вся остальная программа об этом не узнает, не надо будет менять код отправки этого сообщения.
Так это связь сообщения с методом по селектору (имени) является тем, что делает сообщения «ненастоящими»? Ну, так вышеупомянутый вами же #doesNotUnderstand: прекрасно с этой «проблемой» справляется (хотя к этому способу прибегают относительно не часто — видимо, в связывании по имени таки есть какой-то смысл? …но сейчас не об этом). То есть, как и в Erlang-е, в Smalltalk-е сообщение не обязательно связывается с выполняемым кодом по имени метода! Все, сообщения в Smalltalk-е стали настоящими?
Что именно? И почему это не поменяется, если будут другие способы вернуть значение? Например, как на это влияет возможност вызывать функцию, которая вернет значение другим способом?

Если отправляющий процесс не снабдит свое сообщение обратным адресом, то есть своим Pid, то ничего вернуть не получится.
Я не понимаю, к чему вы это написали.
К тому, что для того что бы «вызывать функцию, которая вернет значение» нужно иметь возможность вернуть значение. Этой возможности запросто может не быть — неизвестно кому возвращать даже если очень хочется.
Это ясно, я не понимаю, как это ложится в контекст нашего обсуждения.
В Smalltalk-е тоже прием сообщения и код реакции не связаны напрямую!

Вообще связаны, в штатном для Smalltalk случае, в самом "сообщении" зашита информация какой метод будет вызван для его обработки.


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


сообщение не обязательно связывается с выполняемым кодом по имени метода

Вы "не" не туда поставили. Должно быть "обязательно не связывается".

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

Нет. Я могу знать, что какое-то сообщение попадёт в handle_call или в handle_cast, но от сообщения это никак не зависит. Обработчик зависит от того каким способом отправлено сообщение, а не от его содержания.


А может быть, есть шанс получить акторы без Erlang-овских заморочек?

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


ограничиваясь «нормальными» объектами там в остальных случаях

Зачем нужны «нормальные» объекты? Если не нужен полноценный объект, ограничьтесь обычным значением или структурой.
Не знаю, как там Smalltalk обходит performance-проблемы от этой бесполезной упаковки простых данных в объекты. А бедные C#/Java/etc. с бесконечным boxing/unboxing только маются.

Нет. Я могу знать, что какое-то сообщение попадёт в handle_call или в handle_cast, но от сообщения это никак не зависит. Обработчик зависит от того каким способом отправлено сообщение, а не от его содержания.
Я не про это. В Erlang (если я не прав, поправьте) обработка сообщения заключается в сопоставлении сообщения с образцом и выполнении соответствующего выражения. В Smalltalk это сужается до сопоставления имени сообщения с образцом и выполнение соответствующего метода. Так?
Каких заморочек?
Необходимость работать с разнородными сущностями — заморочка… Но я не хочу здесь и сейчас поднимать эту тему. Я просто пояснил свою мысль, если можно, лучше оставим ее без обсуждения. Просто сойдемся на том, что Erlang ведь тоже еще не идеал?

По той же причине оставляю без комментариев оставшуюся часть сообщения.

В Erlang (если я не прав, поправьте) обработка сообщения заключается в сопоставлении сообщения с образцом и выполнении соответствующего выражения.

Понимаете какая штука. С одной стороны, сказать так можно, но это слишком упрощенная трактовка. Как бы объяснить…


Представьте, что у вас несколько doesNotUnderstand и несколько способов отправить сообщение. В зависимости от способа отправки одно и то же сообщение попадёт в разные doesNotUnderstand. А внутри конкретного doesNotUnderstand оно — да — частенько будет сопоставляться с образцом (но не всегда). И опять же сопоставление с образцом и поиск метода по сигнатуре — это весьма разные вещи. Первое можно редуцировать до второго, но не наоборот.


Просто сойдемся на том, что Erlang ведь тоже еще не идеал?

В Erlang я пару субъективных минусов могу найти, а вот в Elixir до сих пор ни одного существенного минуса не нашёл. И даже сам в лёгком недоумении от этого. По-моему он объективно ближе всех к идеалу в современных реалиях. Не в 100% задач само собой. Я по бэкенду крупных веб-сервисов / мобильных приложений в основном специализируюсь, поэтому остальные сферы применения я просто не буду оценивать. Я мог бы рассказать чем кроме синтаксиса Elixir отличается от Erlang — но это будет слишком оффтопик.

Меня бы заинтерисовало сравнение, чем одно лучше другого и наоборот. Ну, типа java vs kotlin, что бы понять имеет смысл переходить с одного на другое, или овчинка не стоит выделки.

Эх, может соберусь когда-нибудь статью написать. В двух словах, основное дополнение — это метапрограммирование в стиле Lisp (манипуляции с AST). Многие другие плюсы (поддержка самого свежего Unicode, протоколы, примеси, etc.) являются как раз практическим применением этого метапрограммирования.

Понимаете какая штука. С одной стороны, сказать так можно, но это слишком упрощенная трактовка. Как бы объяснить…

Вообще-то так сказать нельзя. Совсем нельзя. Потому что сообщение образатывается выражением receive, а сопоставление по образцу внутри него — это уже работа над данными, и в общем-то пофигу откуда они там взялись, из сообщения, или на месте были порождены… По сути — и в этом вся прелесть эрланга! — вся система сообщений находится вне власти программиста. Он может ей пользоваться, но его воздействие на нееограничивается заброской сообщения в чужой почтовый ящик, и выниманием из своего. А дальше — это уже просто данные.
По сути — и в этом вся прелесть эрланга! — вся система сообщений находится вне власти программиста.
Я так понимаю, вы слово «прелесть» используете в положительном смысле? У Smalltalk-а механизм сообщений тоже находится вне власти программиста. Но только что в этом хорошего? Вроде бы все преимущество Erlang-овского подхода и сводится в конечном итоге к тому, что здесь у программиста больше свободы, нет? И тут уже поднимался вопрос о том, что вроде как в Smalltalk-72 работа с сообщениями была гораздо более гибкой, но по соображениям производительности (но, вроде бы, и не только по ним, на самом деле) от нее пришлось отказаться — что и ставится «в вину» «современному» Smalltalk-у (тут я соглашаюсь), и — как утверждается — вообще делает Smalltalk-овские сообщения ненастоящими (вот тут у меня возникает ряд вопросов, начинающихся с «что такое настоящие сообщения?»).
Я давно уже пришел к выводу, что вы — просто толстый тролль, которого совершенно не волнует вопрос «что есть сообщения», поскольку на него раз пять уже ответили со всех возможных углов, и вы просто с неизвестной мне целью разводите черете что на ровном месте. Вы, конечно, продолжайте, но меня из списка собеседников исключите, я с вами закончил. Спасибо.
Если «к выводу пришел уже давно», то что ж только сейчас-то об этом заявлено… Но это риторический вопрос. Всего доброго!
И опять же сопоставление с образцом и поиск метода по сигнатуре — это весьма разные вещи. Первое можно редуцировать до второго, но не наоборот.
(Так же как Message в Smalltalk-е можно редуцировать до Object, но не наоборот, да?) И не надо редуцировать. Просто в Smaltlalk выделен механизм, которого хватает для обработки сообщений в (условно) 99% случаев. Для «нетипичных» случаев есть механизм, позволяющий разобраться «детально». В Erlang принят другой механизм обработки сообщений. Вам он нравится больше? Замечательно! Но это не основание утверждать, что другой механизм обработки делает сообщения вообще не сообщениями. Вот в другой ветке мы, по-моему, подобрались к искомому ответу гораздо ближе. Я там по мере возможности постараюсь точнее показать «взгляд на сообщения со стороны Smalltalk» (насколько я его понимаю).
частенько будет сопоставляться с образцом (но не всегда)
А в каких случаях не будет?
Представьте, что объекты — это люди, которые выполняют какую-то работу.

И что предлагает Smalltalk? Пересылать людей друг другу вместо обмена сообщениями :facepalm:
Если у вас весь мир состоит из людей и только из людей, то какой выбор? А вообще, да, :facepalm: на эту метафору, больше даже нечего сказать… :) А надо? Действительно нет понимания, что такое объект?

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


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

Объект/актор — это тот, кто может что-то делать сам (имея данные, совершать действия).
Насчет акторов — вам виднее :), но насчет объектов согласиться никак не могу. Объект в ООП — это любая сущность, которую мы выделили во вселенной. Человеку сложно (или невозможно?) работать со вселенной как с единой сущностью, поэтому он выделяет/различает/distinuguis из нее отдельные (адресуемые) сущности/вещи/distinctions— объекты.
Проблема популярного ООП, в том числе и в Smalltalk, что создатели ЯП решили всё подряд назвать объектами
Огромным услием воли я удержался от достойного комментирования этого пассажа :D
(объект) всё-таки неудачный термин, актор — гораздо точнее соответствует идеям Кея
Вы упорно отказываетесь различать объекты и акторы, а это, очевиднейшим образом, разные вещи, что прекрасно видно на приведенном вами примере.
Я вот ни разу не видел книгу, которая могла бы сама себе поменять название или посчитать кол-во страниц в себе. Потому что книга — это просто структура данных (да ещё и иммутабельная, если её не портить), и никаких методов она иметь не может.
Книга не может менять название? Расскажите об этом писателям. И не надо передергивать (или это искреннее заблуждение ввиду некоей Erlang-деформации?), добавляя слова «сама по себе». Объекты (по умолчанию) ничего не делают сами по себе, они лишь реагируют на сообщения — и в этом принципиальное отличие от акторов! Актор — «активный» объект. В ООП-парадигме можно реализовать актор, задав ему соответствующее поведение. В модели акторов часть акторов (наверное) можно охарактеризовать как объекты? (Если есть желание, можно добавить к ним определение «пассивные»?)

Теперь понятно, почему объекты и акторы — разные сущности и не надо их смешивать? Можно считать, что акторы — подмножество объектов, можно — наоборот. Лично для меня первое — более естественно (так что дичью для меня звучат слова «сама по себе»), но в любом случае это не одно и то же множество.

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

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

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

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


I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea. The big idea is "messaging".
I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages. © Alan Kay


Что тут важно? Биологическая клетка или компьютер в сети — это активная действующая единица. На самом деле, термин "объект" крайне неудачно подходит для самой концепции, поскольку имеется в виду субъект действия, который может общаться с другими субъектами посредством обмена сообщениями. Всё остальное вторично.


Именно так реализованы акторы в Erlang/OTP. А объекты в Smalltalk реализованы не так (хотели так, но видимо для 1969 года идея оказалась слишком сложной). Глупо думать о книге, о строке, или о числе, как об отдельном компьютере в сети (даже умозрительно это был бы абсолютно иррациональный оверхэд, вдобавок затрудняющий понимание функционирования сети), поэтому они не могут быть объектами в Кеевском понимании. Вот собственно и всё резюме.


Объекты (по умолчанию) ничего не делают сами по себе, они лишь реагируют на сообщения

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


Книга не может менять название? Расскажите об этом писателям.

Писатель/редактор/цензор/издатель — это уже акторы, они могут изменить название книги, не вопрос (хотя даже у них есть ограничения, например, если книга напечатана, то никто уже не может изменить её название). А книга сама ничего не может, у неё нет никаких встроенных методов для этого. Вы серьёзно не видите разницы?


P.S. Не воспринимайте всё так, как-будто я не знаком с ООП во всех его современных проявлениях. Я специально пишу в такой манере, чтобы Вы могли взглянуть на вещи под другим углом, скинув привычные шоры.

Я не буду продолжать эту ветку дискуссии. Не потому, что мне здесь нечего ответить или она не заслуживает внимания. Напротив — вопрос интересенейший, а дискутировать можно буквально по каждому выдвинутому тезису. Просто это не по теме. Если есть желание — можно перенести обсуждение этого вопроса в другое место …и мы оба знаем, по крайней мере, один вариант ;)

На следующем митапе можем обсудить )

Самый здравый комментарий про ООП, что я слышал.
Но почему бы не посмотреть на вещи ещё шире?
Классы + методы = ООП на уровне процесса, процессы + сообщения = ООП на уровне ОС, распределённые процессы + сообщения = ООП на уровне сети.
Меняется масштаб, суть остаётся одна.
Дело в том, что «Erlang-овский ООП» не предполагает никакого ООП на уровне «ниже процессов» — там начинаются голые данные и функции. По сути, «Erlang-овский ООП» — это Kay-евские тезисы о ООП как о сообщениях за вычетом пункта «все есть объект». Апологетике такого подхода посвящен этот комментарий.

То есть, в рамках «Erlang-овского ООП» «масштабирование» предполагается только «вверх». Можно говорить, что этого достаточно, что делать все объектами — не нужно, но очевидно, что оригинальный («Smalltalk-овский») подход более гибок, так как предполагает «масштабирование» «в обе стороны». При этом у Smalltalk-а есть ряд проблем, часть из которых неплохо решает, к примеру тот же Erlang с акторами. Являются ли эти эти проблемы неустранимыми в рамках аксиомы «все есть объект» — вопрос открытый… В общем, эта тема заслуживает отдельного внимательного и подробного рассмотрения.
Дело то не в языке, а в архитектуре.
Например, микросервисы — это тот же ООП, в чистом виде.
А на чём написан конкретный сервис, вообще не важно.
Дело в том, что «Erlang-овский ООП» не предполагает никакого ООП на уровне «ниже процессов»

С одной стороны — да, с другой — это всё-таки не уровень ОС, это легковесные процессы виртуальной машины. И их может быть много тысяч на одной машине.


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

А по поводу внутреннего устройства, так это и к клеткам применимо. Даже если любой организм состоит из клеток, то внутри клетки очевидно не другие клетки, а митохондрии, рибосомы и т.д.
Дык, и несколько клеток не образуют «клетку». То есть встретить объект, состоящий из других объектов было бы тоже крайне странно. ;)
А пункта «объект должен состоять из других объектов» вроде никогда не было.

3. Objects have their own memory, which consists of other objects.
Поэтому я бы сказал, что пункт «все есть объект» в Erlang тоже выполняется, т.к. нет никакой возможности выполнить какой-то код вне актора.
Поэтому так сказать нельзя, увы… Но это же и не нужно. Зачем пытаться «за уши» притягивать чуждые идеи? Erlang тем и интересен, что «объекты» там как те люди-дикари: на лицо ужасные объектные, добрые (почти) функциональные внутри. …А то так ведь и правда получится плохой Smalltalk ;)
То есть встретить объект, состоящий из других объектов было бы тоже крайне странно. ;)

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


  1. Objects have their own memory, which consists of other objects.

Это формулировка Тима Бадда из книги "An Introduction to Object-Oriented Programming", которая со Smalltalk не особо связана.
А у Кея было так:


  1. Everything is an object.
  2. Objects communicate by sending and receiving messages (in terms of objects).
  3. Objects have their own memory (in terms of objects).

Причём он сам был недоволен, как Бадд переврал его определение, изменив смысл. Вот тут можно подробнее почитать, в том числе и про то, что версии Smalltalk до Smalltalk-80 базировались на модели акторов. В принципе, можно сказать, что Smalltalk-80 свернул на кривую дорожку и отказался от ООП в исходном понимании.


P.S. Собственно, чего тут спорить, Кей тут на днях сам написал, что
Erlang is much closer to the original ideas I had about “objects” and how to use them.
Можете с ним лично поспорить, если хотите :-)

Угу, поэтому состояние объекта и не должно состоять из других объектов.
Ага-ага, и никакой актор не должен пользоваться «услугами» других акторов.
Причём он сам был недоволен, как Бадд переврал его определение, изменив смысл.
Чем был Кэй был недоволен, где «перевран» смысл?
версии Smalltalk до Smalltalk-80 базировались на модели акторов
Агентство ОБС сообщает? Smalltalk-76 однозначно не базировался на модели акторов. Smalltalk-72, если судить по библиографии Хьюитта, просто не мог базироваться на модели акторов поскольку первое упоминание термина «Актор» относится к 73-му году. Более того, сам Хьюитт вроде как говорил, что модель акторов родилась под влиянием первых версий Smalltalk. Это, разумеется, не исключает влияния «прото-акторовских» идей на Кэя, и очень может быть в Smalltalk-72 было что-то подобное. Впрочем, я четких подтверждений, что сообщения в Smalltalk-72 были такими же как в Erlang не нашел — это буду обсуждать в другой ветке, приглашаю принять участие.
В принципе, можно сказать, что Smalltalk-80 свернул на кривую дорожку и отказался от ООП в исходном понимании.
Сказать-то можно все что угодно, надо чтобы эти слова еще и были бы адекватными. ;)
Собственно, чего тут спорить, Кей тут на днях сам написал, что
Erlang is much closer to the original ideas I had about “objects” and how to use them.
Можете с ним лично поспорить, если хотите :-)
Что имел ввиду Кэй — вопрос открытый. Вы умеете читать мысли? Я — нет. Но вот то, что вы постоянно забываете, что мы тут обсуждаем — выглядит вполне достоверной гипотезой :)

Ну спросите Кэя лично, если вам что-то непонятно в его формулировках. В чём проблема то? на Quora забанили? xD


Smalltalk-72, если судить по библиографии Хьюитта, просто не мог базироваться на модели акторов поскольку первое упоминание термина «Актор» относится к 73-му году.

Вот вы дотошный… Ok.
Smalltalk-72 базировался на том, что в 73 году переросло в модель акторов (вот Хьюитт — молодец, не стал всех путать термином "объект", а ввёл новый и более подходящий). Однако, сам Smalltalk пошёл дальше другой дорогой, и отказался от этих идей по performance-соображениям тех лет.

Дык, и несколько клеток не образуют «клетку». То есть встретить объект, состоящий из других объектов было бы тоже крайне странно. ;)


Ну а как же объекты с полями, являющимися другими объектами?
Sign up to leave a comment.

Articles