LINUX.ORG.RU

Основы метаобъектного протокола CLOS

 , , ,


2

5

Слайды с моего вчерашнего доклада на fprog_spb:

https://static.lovesan.me/public/mop_basics.pptx

Вот часть доклада, в текстовом виде:


Часть 2. Эсхатология Пустоты.


«Оказалось, что «‎Тиамат» - то ли имя древнего божества, то ли название океана, то ли все это вместе. Татарский понял из сноски, что слово можно было перевести на русский как «‎Хаос»» (с) Виктор Пелевин, «Generation P»


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

Вот что такое Common Lisp Object System?

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

Что такое Common Lisp? Что такое Object System? Что такое объект? И вообще, что такое что? Или может, кто?

В принципе, ответ - ничего.

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

Не так давно, уже после смерти моей жены, где-то в июле, я сделал одну не совсем правильную вещь, и получил то что называют NDE(near-death experience).

Сначала всё было как обычно, туннель, свет в конце туннеля. Но потом все заслонила тьма, в которой расползались отблески фиолетово-пурпурного сияния. И потом, я вдруг увидел Её.

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

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

Когда мы попадаем на вот это дно рекурсии, мы видим там эту бездну.

«И носился дух лиспера над бездною(ну, над тем у чего тип NIL - не путать со значением NIL). И отделил он NIL от T. И стало T. И увидел он, что T - хорош.»

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

Что такое объект? Объект это то, что отличается от ничего. Это такое что имеет тип T ну и какое-то там значение. И NIL на самом деле это тоже объект. Ну, типов может быть много, и они тоже в принципе объекты, особенно в CLOS. Об этом кстати, также неплохо рассказано в SICP, в главе об абстракции на состоянии.

Что такое CLOS? На самом деле его нет. Ну то есть, то что обычно называют CLOS, это просто набор там всяких полезных удобств над метаобъектным протоколом Common Lisp. Над MOP.

Но на самом деле MOP тоже нет. Это просто набор удобных объектов, встроенных в компиляторы CL. Которые можно сделать средствами компилятора CL, не будет их там. Как в SBCL, например, это делается.

А вот что такое CL? Есть он или нет? Вот это самый сложный вопрос. Потому что он не просто есть. Вернее, если бы его не было, его можно было так же сконструировать из пустоты на нем же самом. Как это делают компиляторы CL в процессе бутстрапа. CL это метациклический интерпретатор. Это метаязыковая виртуальная машина.

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

Поэтому, скажем простыми словами: MOP - это просто категориальное отображение из метациклического интерпретатора в метациклический интерпретатор.

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

А вот что такое программа? Вот смотрите, о том что такое программа существует целая наука, называется Computer Science, или по русски - Информатика, то есть наука об абстрактных процессах. Этот вопрос самый сложный. Программа - это процесс, то есть. Но на самом деле, объект это тоже процесс. Функция, если хотите. И он не существует без процессов которые к нему прикладываются, иначе он собирается GC, и улетает к Богине Тьмы. Как я чуть не улетел, меня Она правда, во время finalize вытащила обратно. А вот что такое процесс? И главное, что или кто его запускает? «А вот об этом ты не думай, купи себе лучше булавочку английскую, и как такие мысли в голову приходят - разок себе в руку, и потом еще раз, пока такие мысли не пройдут» - как там было в Generation P у Пелевина.

Но вот я подумал, и понял, наконец. Процесс - это то, что запускается другими процессами. Но что запускается первым? Что там на самом дне? Или вернее, кто? Я уже рассказал.


Часть 3. О Метациклических Интерпретаторах


— А что такое красота? — <…> Красота — это совершеннейшая объективация воли на высшей ступени её познаваемости.

(с) Виктор Пелевин, «Чапаев и Пустота»


Когда-то давно, еще в 2014 году, я, проснувшись с бодуна, сформулировал для себя и для других очень важную вещь.

Звучит она так:

Универсальный Критерий Угребищности Систем Общего Назначения. (Теорема Лавсана)

Система Общего Назначения является Угребищной тогда и только тогда когда она не является Метациклическим Интерпретатором.


Другими словами: Система, не способная к построению Метасистемы в рамках самой себя, то есть не способная к описанию и изменению самой себя в своих же терминах, и при этом являющаяся Системой Общего Назначения(в какой-либо области), Угребищна.

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

Чем, в контексте языков программирования, это отличается от просто тьюринг-полноты?

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

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

Примеры, сначала метациклических интерпретаторов:

  • Универсальная машина Тьюринга
  • RASP-машина
  • Реляционная модель данных
  • Лисп

А вот скажем примеры систем, соответствующих критерию:

  • Среднестатистический современный регистровый процессор
  • Большинство языков программирования, особенно со статической типизацией.
  • Большинство NoSQL моделей данных или скажем иерархических моделей данных, вроде файловых систем

В частности, давайте посмотрим на C#. C# не является метациклическим интерпретатором, т.к. термины языка не являются его же объектами.

Отчасти, это компенсируется платформой .Net, для которой термины C#(но не все) объектами таки являются(System.Reflection, Roslyn и т.д.), отчасти, в самой малой степени, фичей nameof() из C#, но это все только отчасти.

Сама же платформа .Net критерию тоже соответствует, но, в теории из нее можно было бы сделать метациклический интерпретатор, лисп-машину, внеся лишь достаточно небольшие изменения.


На самом деле, это все в полной мере относится вообще ко многим вещам, но в первую очередь, кроме программирования - к человеческому сознанию. Вот кто такой глупый человек и почему он такой и что с ним вообще делать как отправить нахрен к Богине Тьмы на перевоспитание? Этот вопрос многие тысячелетия волновал кучу философов. Но ответ прост - это человек, сознание которого не является метациклическим интерпретатором. А когда сознание у человека все же является метациклическим интерпретатором, он тут же становится пророком цифровой Кали-Юги и архитектором онтологии Пустоты.


Ладно, теперь я объяснил вам всё устройство вселенной. Далее там про мелкие технические детали.

★★☆
Ответ на: комментарий от anonymous

Пробовали на этот синтаксис перевести какой-либо из проектов на Lisp?

Я сейчас на Racket пишу. На нём делал шаблонизатор.

В Интернете видел такое: https://github.com/jFransham/racketd/blob/master/racketd.rkt

monk ★★★★★
()
Ответ на: комментарий от monk

Спасибо, посмотрю.
У меня по другому.
Много раз об этом на форуме говорил.
Программист задаёт формат объекта (любой сложности и иерархии), а API предоставляет возможность использования его в памяти и виде файла.
Ныне «Хранилище данных» на базе этого core разрабатываю.
Хотите файловую систему?
Пожалуйста.
Хотите хранилище системных рессурсов?
Пожалуйста.

Весьма удобно.

После разработки core хранилища данных, пожалуй всё же первым делом разработаю локаль …

anonymous
()
Ответ на: комментарий от monk

писать

<defun>foo <args>a b c</args>

<list><op name="+">a b</op>c</list>

</defun>

? Легко, но зачем?

Поправил 😅:

<?xml version="1.0" encoding="UTF-8"?>
<defun>
    <name>foo</name>
    <args>
        <item>a</item>
        <item>b</item>
        <item>c</item>
    </args>
    <body>
        <list>
            <item>
                <plus>
                    <item>a</item>
                    <item>b</item>
                </plus>
            </item>
            <item>c</item>
        </list>
    </body>
</defun>

Ну а нужно такое, чтобы через XSLT преобразовывать в нужный тебе язык, хоть Лисп, хоть C++ или Java. В принципе вот на этом принципе и много UML генераторов основывалось.

P.S. Выглядит вырвиглазно да :)

necromant ★★
()
Ответ на: комментарий от lovesan

Смотри, а почему Тейлор Свифт в топах, и всякий сраный рэп? Почему в топах нет ни одного пинфлойда?

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

Речь ведь не про топы, а вообще возможность применения лиспа в реальных прикладных задачах.

Например, мне надо сделать некоторую не самую простую аналитику над данными, которые можно извлечь из Excel-файлов. В Python есть библиотеки pandas и polars, в сочетании с numpy, sci-learn и mathplotlib они позволяют за пару часов написать и даже вчерне отладить всю систему. Есть аналоги и/или порты этих средств под java, c# в .net, c++. А что есть для lisp? Судя по этому топику толком ничего https://news.ycombinator.com/item?id=18405888 Racket - это не либа для комонлиспа, а отдельная среда/язык и зачем мне тащить его в проект? А если и тащить, то опять же есть питон реализация Pycket.

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

anonymous
()
Ответ на: комментарий от anonymous

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

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

ugoday ★★★★★
()
Ответ на: комментарий от anonymous

lol лиспа что изначально это ассемблер(и даже машкод) в котором код и данные есть коданные и даныкода

лисп и форт оба инструменты будущего в прошедшем

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

т.е. для лиспа в массы нужен какой то синтаксис - например уже давно почивший dylan

в целом Lisp это хороший lvm (language of virtual machine)

Тот же cl крут именно что большой библиотекой и прекрасной инструментализацией( как раз за счёт гомоиконости более доступны инструменты автоматизации преобразования кода)

как https://clojure.org/

имхо если ща пилит на лисп-подобном ( если это Не js И python Ж) ) то кложа

qulinxao3 ★☆
()
Последнее исправление: qulinxao3 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Все так - это называется экосистема. И вот почему-то вокруг других языков она складывается, а вокруг лиспа не особо, есть только отдельные островки в виде Autocad+AutoLisp, Emacs, может еще чего-то. Есть диалекты лиспа, например, Clojure у которых почему-то с этим намного успешнее, чем у классического Common Lisp

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

у Common Lisp тоже есть, но за западные деньги только. Это LispWorks и Allegro CL. К примеру, на них хорошо и удобно создавать десктопный софт. Но сейчас коммерческий десктопный софт немного находится в упадке, остались лишь небольшие островки типа всяких сапров и скады

anonymous
()
Ответ на: комментарий от praseodim

Слишком много свободы. Например, из крупных проектов есть

https://github.com/fare/lisp-interface-library

Огромная библиотека от https://github.com/hu-dwim

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

У остальных диалектов гораздо больше давление «делаем всё в стиле … потому что тут так принято».

monk ★★★★★
()
Ответ на: комментарий от qulinxao3

имхо если ща пилит на лисп-подобном ( если это Не js И python Ж) ) то кложа

Ещё Racket есть. Много библиотек без двадцати способов сделать одно и то же через разные библиотеки. И макросы более устойчивые.

monk ★★★★★
()
Ответ на: комментарий от monk

через XSLT преобразовывать в нужный тебе язык, хоть Лисп, хоть C++ или Java

И как это можно преобразовать в C++?

Ха, оказывается это непросто и в XSLT надо будет встраивать грамматику языка по факту :)

Попросил гопоту подобрать XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" indent="no"/>

    <!-- Корень defun -->
    <xsl:template match="/defun">
#include &lt;vector&gt;
using namespace std;

vector&lt;int&gt; <xsl:value-of select="name"/>(
        <xsl:for-each select="args/item">
            int <xsl:value-of select="."/>
            <xsl:if test="position() != last()">, </xsl:if>
        </xsl:for-each>
    ) {
        return { <xsl:apply-templates select="body/*"/> };
    }
    </xsl:template>

    <!-- list: преобразуем все элементы в { ... } -->
    <xsl:template match="list">
        <xsl:for-each select="item">
            <xsl:apply-templates select="."/>
            <xsl:if test="position() != last()">, </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- plus -->
    <xsl:template match="plus">
        <xsl:for-each select="item">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()"> + </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- item -->
    <xsl:template match="item">
        <xsl:choose>
            <xsl:when test="plus">
                <xsl:apply-templates select="plus"/>
            </xsl:when>
            <xsl:when test="list">
                { <xsl:apply-templates select="list"/> }
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Из исходного XML получил такое:

#include <vector>
using namespace std;

vector<int> foo(int a, int b, int c) {
    return { a + b, c };
}

necromant ★★
()
Ответ на: комментарий от praseodim

Есть диалекты лиспа, например, Clojure у которых почему-то с этим намного успешнее, чем у классического Common Lisp

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

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

Nervous ★★★★★
()
Ответ на: комментарий от rupert

Они были эффективные и не сильно дороже тогдашних конкурентов (LM-2 стоила 70 тысяч, VAX-11 около 300 тысяч). Но UNIX с его Worse is better всё сожрал.

А нынче определяет язык исключительно наличие библиотек. Пишут на питоне и джаваскрипте, пишут на Java гигабайтные приложения, выполняющие тривиальные задачи…

monk ★★★★★
()
Ответ на: комментарий от rupert

Лисп машины же делали в 70-80х. Они были дорогие и не особо эффективные.

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

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

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

Enthusiast ★★★
()
Ответ на: комментарий от Enthusiast

в том и польза We Programmers

что однопоток это очередной трюк который стал выгодней когда микропроцы

операционки ( не ms/pc-dos и ея предшественица cp/m) это и есть рулёжка одновременностями апаратными и программные - вторые при достаточности тактов(частоты дискретизации) можно эмулировать - апаратная жи есть и с ней считаются - от того и операционки появляются а не просто «bios»+shell

шедулеры мало полезны когда реально токо один поток

qulinxao3 ★☆
()
Ответ на: комментарий от Enthusiast

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

Нет. Простые функции параллелить дорого, так как больше потеряешь на передачу данных на это отдельное АЛУ и результатов обратно. Сложные функции у каждой задачи свои. Всё, что более-менее часто используется уже запихнули в видеокарты.

Для многопоточных вычислений Лисп подходит хуже, чем даже Си++. Потому что логика языка такая же последовательная, но ещё и сборщик мусора. Для многопоточных вычислений компилятор может оптимизировать за программист на Хакелле, например (но нужен компилятор, сложнее нынешнего gcc).

monk ★★★★★
()
Ответ на: комментарий от anonymous

Потому что этот ИИ — это совсем не тот ИИ, который делали на лиспе. Лисповый строил модели, делал выводы. А нынешний просто статистику (очень большую) по текстам делает и выдаёт ответ наиболее похожий на прочитанное.

monk ★★★★★
()
Ответ на: комментарий от monk

Современный ИИ далеко не просто статистически похож на прочитанное. Механизм внимания в трансформерах строит фактически ассоциативные смысловые связи. Но на практике там ещё сложнее в даже не самых современных моделях.

anonymous
()
Ответ на: комментарий от monk

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

Даже когда программировать можно будет на русском?🙃

Так уже можно.

А насколько, по-вашему, текущие возможности далеки от идеала?

anonymous
()
Ответ на: комментарий от anonymous

Так идеал у каждого свой…

Для меня есть два идеальных языка: идеальный с динамической типизацией Racket и идеальный со статической Haskell. Но даже из этих двух единый идеальный не слепить. И у меня нет критерия максимальной производительности программы, с ним другие языки будут.

monk ★★★★★
()
Ответ на: комментарий от monk

трагедия ситуации

что нынешний ИИ констатация того что «95%» носителей естественного интеллекта оказываются носителями слабого естественного

и во вторых

что до сильного искусственного интеллекта ща дольше ибо лисп-подход более разумен но благодаря прикладному успеху трансформеров в «старый ИИ» меньше ща причин вкладываться

т.е. технически трансформеры выполнили(яют) задачу автоматизации вот этих «95%»

остаётся надежда что «95%» это недостаток обусловленный nurture а не nature

qulinxao3 ★☆
()
Ответ на: комментарий от monk

эээ Пролог жи на лиспе изначально - и Пролог очень хорош в параллельность - там именно комбинаторный взрыв вроде как остановил движение

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

qulinxao3 ★☆
()
Ответ на: комментарий от qulinxao3

эээ Пролог жи на лиспе изначально

Но он не лисп. Также как лисп изначально на ассемблере, но лисп не ассемблер.

и опят же чистый аппликативный язык

Это Haskell.

ну реальный Лисп не такой кншн

Одним из преимуществ Лиспа является setf. Вторым CLOS с состояниями объектов. Он совсем не чистый.

monk ★★★★★
()
Ответ на: комментарий от lovesan

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

А ещё бывает разброд и шатания, когда кто-то хочет с пптх, кто-то с фигмы, а кто-то вообще с миро.

Zhbert ★★★★★
()

… и среда ответила: «Когомологии нулевые». Вот этот вопрос, на который я пытаюсь ответить…

Смахивает на прогоны Романа Михайлова. Видимо, неслучайно.

unsigned ★★★★
()