Re[6]: понимание ООП Алана Кея
От: vdimas Россия  
Дата: 22.03.23 09:39
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

V>>Это следствие другого принятого решения — компиляции кода под архитектурно-независимую VM, т.е. оно перпендикулярно ООП-парадигме.

S>Нет, не следствие. Тот же Паскаль от рождения компилировал в платформенно-независимый P-код, и это никак не помогает ему в реализации подобных сценариев.

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

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

Аналогично в VB — компиляция происходит в нейтив, но для отладки используется P-код в памяти, без сброса образа на диск.


S>И вообще к компиляции во что бы то ни было это отношения не имеет — в gemstone по проводу едет не "скомпилированный код", а его AST представление.


Что не требуется уже на уровне переносимых объектных файлов.


S>Да, перпендикулярно — в том же Лиспе никакого ООП нет, а вот code as data есть. Оттуда и слизано в SmallTalk.


Я уже говорил — из Форта, скорее, который являлся чем-то вроде бинарной версии Лиспа.
Натяжка Смолтолка на Лисп, таки, слишком смелая.
Зато на Форт прямая — под капотом была стековая VM с двумя стеками из Форта и такой же шитый код по результату работы JIT.
Это почему к эффективности Смолтолка были вопросы, из-за недостаточно умного JIT.

Зато PostScript, который является развитием Форта, вполне себе ездит с устройства на устройство и прекрасно исполняется.


V>>А это следствие еще одного решения — хранения метаинформации вместе с кодом.

S>Это всё одно и то же решение — code as data.

Повторюсь, любой объектный файл (или архив их в объектной библиотеке) над переносимой платформой (например, llvm) представляет из себя то же самое.
Даже в Паскале, Си и С++.
К языку это перпендикулярно.


V>>Сам Форт — это, по-сути, "бинарная" версия Лиспа, работающая эффективнее Лиспа порой на порядок.

S>Ну, я в форте не спец, но особых сходств с Лиспом не вижу.

Сходство с Лиспом там в общей схеме работы интерпретатора, который двухфазный:
1. компиляция во внутренее представление;
2. исполнение этого внутреннего представления.

Собсно, эти два языка отшлифовали принципы построения интерпретаторов, выделив их в отдельный класс ЯВУ.

В Форте была еще третья фаза — сохранение полученного скомпиллированного образа, в т.ч. одной из опций сохранения было удаление метаинформации ("словарей" в терминологии Форта) и неиспользуемых процедур ("слов" в терминологии Форта), т.е. запуск сохранённого образа затем сразу переходил ко второй фазе, т.е. не требовал текстовых исходников, что и определило поплярность Форта во встраиваемом оборудовании. Собсно, это был первый успешный язык достаточно высокого уровня, применённый во встраивемых сценариях.
https://habr.com/ru/post/29967/

Далее сходство в организации контекста компиляции ("контекст" в терминах Лисп и "набор активных словарей" в терминах форта).
В Форте, в отличие от Лиспа, можно управлять "контекстом" явно.
В Лиспе только неявно.

Далее сходство в том, что код представляет из себя адреса символов и литералов.
Плюс в Форте численные литералы были представлены значениями, а не адресами.

Еще отличие Форта в том, что в коде хранится адрес исполняемой процедуры слова, в то время как в Лиспе хранился адрес метаинформации символа, т.е. Чарльз Мур убрал лишний уровень косвенности в процессе работы программы. Однако же, обратным поиском адреса в Форте запросто памятся на "слова". Т.е. Мур сделал размен эффективности оперирования метаинформацией на эффективность исполнения.

Посмотреть "код как данные" можно командой "see".
Любопытства ради выполни в любой онлайн Forth IDE программу:
see see


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


Подтверждаю.
Задолго до выхода этой статьи в 1996-м я однажды плюнул на кривые ассемблеры под i35/i38/i48/i51 архитектуры и наваял кросс-ассемблер за один рабочий день.
Это вместе с макросистемой.
И сам ассемблер получился намного мощнее, т.к. изкаробки шла возможность описывать вычисления формул времени компиляции, офигенно помогало — достаточно было изменить одну константу (точное значение частоты кварца в моём случае) и все остальные константы можно было расчитать по достаточно сложным формулам прямо во время компиляции.

Да и, до первых виденных ЭВМ прилично упражнялся на программируемом калькуляторе MK-61, это тот же Форт, вид сборку.
Поэтому, программирование на Форте чуть позже зашло как к себе домой. ))


V>>Плюс расплатой за эффективность стало явное оперирование состоянием стека (вернее, это был способ резко повысить эффективность на технике тех лет).

S>Эмм, в Форте же вообще нет динамической памяти.

Есть.
Оперирование динамической памятью явное.
Это самые базовые слова:
— "," — выделить ячейку в динамической памяти и скопировать туда значение с вершины стека;
— "@" — читать из памяти число адресу на вершине стека;
— "!" — писать число из второй ячейки стека по адресу на вершине стека.

Есть вариации шириной не только в слово, но и в полуслово, в байт, в двойное слово.

Со строками/массивами аналогично, копирование и т.д.
— "S=" — сравнение двух строк, заданных адресами на стеке и т.д.
— "-TH" — на стеке адрес массива и индекс, после исполнения на стеке элемент массива.


S>Так что там нет ни неизменяемости, ни списков, ни сборки мусора, в общем, ничего из Лиспа в нём нет.


В Форте можно описать произвольные структуры данных в памяти.

Сборка мусора в Лиспе, опять же, реализована по-разному.
В некоторых реализация сборка мусора вызывается каждый раз при исчерпании текущих свободных ячеек в предвыделенном пуле их, что может провоцировать (и провоцировала) сборку мусора даже когда потребности в этом не было, т.е. не было "забытых" объектов.
В других реализациях сборка мусора вызывается явно в рамках борьбы такими с холостыми срабатываниями.

В любом случае, с многопоточной сборкой мусора в современных VM этот подход имел мало общего.

Да и сборщик мусора консервативный, а не точный, как в Java или .Net.
Т.е. не перемещает данные (не уплотняет память).
Т.е., не помогла особо метаинформация.

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


V>>В итоге ООП выиграло гонку популярности у ФП по очевидным причинам: ООП включало в себя целиком все известные на тот момент парадигмы — структурную и функциональную.

V>>И если, скажем, ФП представляло из себя набор ограничений, то ООП представляло собой набор инструментария, в т.ч. для разработки другого инструментария, т.е. парадигма заведомо разрабатывалась для "расширения", а не ограничения. Первая человеческая IDE на Смолтолке с кучей функциональности (например, первый в мире автоматический рефакторинг) — самое яркое тому подтверждение. ))
S>И смолток так и остался уделом кучки гиков. А популярность ООП обрело только с выходом плюсов.

С выходом объектного Паскаля и первых версий VB от MS, скорее.
А да, еще купленый и допиленный до Visual FoxPro (объектность там была на механике COM).

В те года С++ обитал в стадии "Си с классами" и точно был уделом гиков.

Плюсы были "распробованы" сообществом ближе к середине нулевых.
И во многом благодаря COM/OLE/ActiveX/MFC (а позже ATL) в Windows.

Наверно, нет смысла напоминать, что положение Windows и MS на тот момент можно было считать исключительным.
Вся отрасль тянулась за успехом их Windows и Офиса.
Оба продукта активно переписывались с Си на С++ в 90-е.
Даже драйвера устройств. ))


V>>Вдогонку, ООП-парадигма включила позже естественным образом даже модели из паралельных вычислений — модели акторов с мейлбоксами и модели конкурирующих сигналов.

V>>Т.е. ООП-парадигма на сегодня является наиболее полной парадигмой из всех известных.
S>Это если смотреть на всё через призму ООП парадигмы. Скажем, Java на уровне 1.2 полностью реализует всю ООП парадигму.

Java изначально ограничила саму ООП-парадигму и .Net совершила ту же ошибку в первоначальном дизайне.
И только сейчас пытаются залатать пробелы.

Помнишь обсуждение хотя бы новых управляемых указателей на методы в .Net?

А обсуждение типов-делегатов все нулевые года?
Надо ж было умудриться описать делегаты как объекты, что делегаты с одинаковой сигнатурой стали несовместимы. ))

Это серьёзный косяк, как ни крути.
C++ эту ошибку не совершал.


S>Тем не менее, внезапно оказывается, что современное программирование не удовлетворяется одной лишь ООП парадигмой, и на рынке рулят мультипарадигменные языки, в которые проникли чисто-ФПшные штуки.


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

Да и Смолтолк приобрёл свои характерные черты не в первой версии 72, и даже не в 76, а только в 80.


V>>Через const в С++ можно выразить абсолютно все сценарии вокруг иммутабельности целиком, но это будет лишь небольшая вершинка айсберга всех сценариев, покрываемых const.

S>Напомните мне, как мне через const в c++ обеспечить неизменяемость аргумента, переданного мне в метод? Не запретить моему методу менять аргумент, а запретить внешнему коду менять мой аргумент?

Элементарно.
Для этого значение должно быть const в контексте внешнего кода.
Т.е. значение может быть const по всей иерархии "внешности", вплоть до объявления.
Или может приобретать признак const лишь с некоторой точки вычисления.
Это на выбор программиста.

Если начинать с момента объявления, то получаешь это:

Через const в С++ можно выразить абсолютно все сценарии вокруг иммутабельности целиком

Что будет лишь малой частью всех возможных сценариев по слишком очевидной причине (тут уже сложно не материться) — ввиду наиболее сильного наложенного на сценарий ограничения.

Странно, что мы вообще спорили тогда и сейчас вокруг подобной элементарщины...
Отредактировано 22.03.2023 10:25 vdimas . Предыдущая версия . Еще …
Отредактировано 22.03.2023 10:15 vdimas . Предыдущая версия .
Отредактировано 22.03.2023 9:46 vdimas . Предыдущая версия .
Отредактировано 22.03.2023 9:42 vdimas . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.