сделал на досуге крохотный ивент-дривен рантайм, потом подумал “надо бы внести в мир равенство и справедливость, давайте сделаем по потоку на обьект?”
сказано-сделано, работает. правда, в голову лезут два назойливых вопроса:
- нафига это надо? :)
- как на этом правильно программировать?
после где-то двух суток размышлений внезапно попёрло и начался
мысленный понос:- есть обьекты со свойствами (приватными) и методами, а также сообщения, которыми они обмениваются
- э-ээ, что-то многовато сущностей, давайте фичекатить.
зачем нам методы? давайте введем иерархию классов, нет, разобьем их на аспекты, нет, давайте отделим их от обьектов совсем.
обзовем это rule set’ом. т.е. отдельно от данных существует “мега-паттерн-матчер” который для кортежа (обьект, очередь сообщений) подбирает правило и кормит ему этот вход - зачем нам return? зачем нам стэк? правило = (обьект, очередь сообщений) => (получившиеся сообщения)
- зачем нам переменные? по сути, обьект – это (id, state). если предположить, что такты синхронные, то мы можем на каждом такте фигачить весь свой стэйт сообщением себе же. то есть, все сообщения, посланные в этом такте, приходят одновременно.
ура. мы заодно выбросили очередь сообщений, которая тоже раньше была стэйтом. и решили проблему с лайфтаймом сообщений – все пришедшие сообщения уничтожаются после их обработки. от стэйта остается (id, сообщение) - зачем нам id? потому что object lifetime. и потому что обьекты нужно как-то идентифицировать. сначала разберемся с лайфтаймом. предположим, что обьект после каждого такта работы системы уничтожается. и создает новые обьекты посылкой специального сообщения.
- как тогда идентифицировать обьект? очень просто, по его state, т.е. предположим, обьект имеет 2 переменных (x, y).
тогда чтобы послать сообщение i обьекту, требуется выплюнуть из себя кортеж (i, xDest, yDest). чтобы послать сообщение всем обьектам, x которых = xDest, посылаем (i, xDest, null). чтобы послать вообще всем обьектам, посылаем (i, null, null).
кстати, это очень приятно напоминает всякие штуки из квантмеха вроде того, что две частицы не могут иметь одинаковую энергию :) - оп, а обьектов у нас уже по сути и нету. есть сообщение (createObjectWithProperties, x, y), и остальные сообщения, которым посчастливилось в тот же такт работы системы попасть в те же координаты (или в общем случае – у которых свойства являются подмножеством свойств сообщения createObjectWithProperties)
таким образом попутно лечится противный вопрос “сообщение – это обьект или нет?” - для простоты, предположим, что все свойства обьекта дискретны и множество их возможных значений – счетно. а если ограниченно, то вообще шикарно. но вроде счетности достаточно :)
тогда система представляется битовой матрицей (n^N)*(i+1), где i - кол-во возможных уникальных типов сообщений, n - кол-во возможных значений каждого из свойств обьекта, N - кол-во свойств.
т.е. в каждой точке “пространства” существует n+1 битная маска, где бит 0 означает наличие там обьекта, а остальные биты отвечают за пришедшие к нему в этом такте сообщения. - как это программировать?
очевидно, нужно создать набор правил, ну, правда, они будут больше похожи на законы физики, но это даже хорошо. мы автоматически получаем emergent behaviour возведенный в абсолют, т.е. абсолютно гомогенные обьекты формируют всякие сложные гетерогенные бихевьоры.
потом, выставляя биты, вводим начальные данные. и ставим несколько нулевых битов, ну, чтобы обьекты какие-то посоздавать. добро пожаловать в перфокарты :) - далее можно просто итерировать систему, и она будет работать. система замкнутая и на вид (не помню как формально доказывается) тьюринг-полная, особенно если множество неограниченное.
а еще она идеально параллелится (хоть по процессору на точку), вот правда всё упирается в bandwidth между точками. о, хехе, мы можем ввести явным образом latency доставки сообщений, ну, к примеру, равную расстоянию Хэмминга между матрицей отправителя и матрицей получателя.
правда, для этого придется построить гиперкуб – это немного непрактичный способ постройки многопроцессорной системы, ну вообщем можно ввести какую-нибудь другую меру, которая будет соответствовать другой организации связей между процессорами.
null можно заэмулировать тернарной логикой (по 2 бита на бит получателя), потому что составлять всю матрицу из тритов у меня мозг (пока) отказывается :)
дети, дети, мы открыли скорость света! :) - а еще, obviously, можно дописывать в нее биты и считывать биты. voila, работает.
- оставшийся неотвеченным вопрос – нафига всё это надо? :)
no subject
Date: 2009-05-20 12:38 am (UTC)А в целом - офигенное открытие.
Матрицу же логики тритов легко себе представить, если нарисовать два события и переход между ними; на первом событии три логических значения, на втором два (ну типа булева в пределе); из трех логических значений одно остаётся ложью, одно вечная истина, а одно - нечто, переходящее в истину.
no subject
Date: 2009-05-20 12:44 am (UTC)и за логику тритов тоже спасибо, действительно просто :)
no subject
Date: 2009-05-20 12:57 am (UTC)no subject
Date: 2009-05-20 01:25 am (UTC)no subject
Date: 2009-05-20 05:48 am (UTC)Есть мнение, что программирование в терминах конечных автоматов -- есть наивысшее благо.
no subject
Date: 2009-05-20 04:07 pm (UTC)на этом можно фигачить симуляции всяких забавных хреней. да и вообще, вещь в себе. чем-то напоминает game of life
no subject
Date: 2009-05-23 10:01 pm (UTC)no subject
Date: 2009-05-23 10:12 pm (UTC)правда, это скорее не задача а пока размышления.
то есть, на вопрос "как нужно думать, чтобы было удобно программировать такую штуку под решение прикладных задач" я для себя еще ответа не нашел