Как стать автором
Обновить

Комментарии 209

А где можно увидеть определение того, что такое «интенциональное программирование»?

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

Нет, не получается. Во-первых, эта конструкция не нагляднее лиспа (который нифига не естественный язык). Во-вторых, она еще не стала ЯП, потому что, собственно, смысл конструкций интерпретатору как задавать?

Ну и в-третьих, в вашей последней конструкции как определить, атом имеет электрон, или электрон имеет атом?
Это, как раз, не очень сложно. Можно доопределить, что при одинаковых вопросах первым идёт субъект, а вторым — объект.

А по теме — для того чтоб такую штуку завести, нужно долго и много кодить на обычных ЯП, что лень, ибо выигрыш не очевиден. Какие-нибудь примеры рабочих систем, чтоб пощупать, уже есть?
Каждое такое «доопределение» отдаляет систему от естественного языка.

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

Ага, а компилятор/интерпретатор такой где взять, да еще и с гарантированной семантической однозначностью?
Ну в Inform7 же сделали что-то подобное
Угу, вопрос, насколько оно действительно разбирает произвольное предложение.
Можно доопределить, что при одинаковых вопросах первым идёт субъект, а вторым — объект.

А можно заставить парсер интерпретатора строить оба варианта дерева и выбирать тот, который имеет смысл в данном контексте.
выбирать тот, который имеет смысл в данном контексте.

Для этого нужно научить парсер понимать смысл сказанного, ага.
Я не зря сказал «парсер интерпретатора». Имеется в виду осмысленность в контексте среды выполнения, конечно.
Так все равно надо смысл понимать. То, что мы сузили зону допустимых вариантов, нам еще не сильно помогло. А если мы будем ее сужать до однозначности, мы получим DSL со всеми вытекающими.
Не обязательно. Достаточно определить является это субъектом, и может ли он выполнять действия. Файлы .qsl загружаются в БД. В ней же можно хранить такую онтологию.
Эээ, но в приведенном примере и атом, и электрон — субъекты, и они оба могут выполнять действия.
Электрон часть атома, потому это скорее атом имеет, чем электрон. Я к тому, что это все формализуемо (пока).
Так вам для этого нужно научить систему знанию, что электрон — часть атома.
Да
электрон ?что есть ?что часть ?чего атом.
… и сразу вы влетаете в две замечательных ситуации. Во-первых, ваша инструкция говорит, что «электрон — это часть атома», или «часть атома — это электрон»? Но это ладно, это мелочи. Что веселее — это то, что теперь вам надо создать в системе правило, что сущности, связанные отношением «а — это часть б», могут вступать в отношения «б имеет а» только в таких ролях.
Что веселее — это то, что теперь вам надо создать в системе правило, что сущности, связанные отношением «а — это часть б», могут вступать в отношения «б имеет а» только в таких ролях.
Ну а как же иначе.
Вообще-то это сильно забегая вперед. Сейчас вы уже касаетесь базы знаний, для которой (в частности) этот интерпретатор создается. И на данных которой сможет работать.
Ну а как же иначе.

Угу, осталось выяснить, как вы будете это задавать, сколько ресурсов на это уйдет, и чем это будет отличаться от NLP.

Сейчас вы уже касаетесь базы знаний, для которой (в частности) этот интерпретатор создается.

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

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

Ну и в-третьих, в вашей последней конструкции как определить, атом имеет электрон, или электрон имеет атом?
Слева от глагола актор (валентности «кто» и «что»), справа актант (валентности «кто» и «что»). При построении дерева делаются соответствующие пометки.
Информации по нему не много.

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

Поэтому я переформулирую вопрос: что вы называете «интенциональным программированием», когда приводите список недостатков и достоинств в начале статьи? У мне, если честно, создается ощущение, что вы приравниваете его к «программированию на естественном языке».

С исполнимыми инструкциями кода проблем нет.

И как же вы планируете это реализовать?

Слева от глагола актор (валентности «кто» и «что»), справа актант (валентности «кто» и «что»).

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

И как же вы планируете это реализовать?
Код на видео уже работает.

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

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

Код на видео уже работает.

Так как же?

Нет, это свойство любого естественного языка.

Свойство любого естественного языка — избыточность (и, как следствие, многозначность).

Все множество языков разбиваются на жесткий порядок субъект-глагол-объект (как в английском)

Очень. Смешно. «Down the stairs came the dog».
Нет, не смешно. Это не каноническая форма английского языка. И там, откуда вы этот пример выдрали говорится, то такая инверсия возможна только некоторых случаях, когда по смыслу понятно кто объект а кто субъект. Или вы хотите, чтобы я бросил все, что нужно реализовывать и сосредоточился на ненужной (в данном случае) проблеме перестановки слагаемых. Это не художественная литература, здесь такой проблемы нет и не нужно притягивать кота за яйца.
Это не каноническая форма английского языка.

Here comes the bride — это тоже не каноническая форма?

некоторых случаях, когда по смыслу понятно кто объект а кто субъект

Ключевое слово — «понятно по смыслу».

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

Если вы накладываете на язык ограничения, то он становится все менее и менее естественным. Это само по себе не проблема (собственно, наоборот, ubiquitous language и DLS как раз идут по этому пути, и именно для повышения точности), просто это обратное тому, что вы заявляете.
Ключевое слово — «понятно по смыслу».
Ну какой смысл в простеньком интерпретаторе. При введении онтологий, эта проблема возможно решаема.

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

Тем самым вы делаете из естественного языка язык программирования.

Чтобы одновременно и оперировать словами естественного языка и не заморачиваться с разбором всех его многообразий.

Так вы хотите оперировать словами естественного языка (что, в общем-то, делает большая часть языков программирования), или естественным языком?
Тем самым вы делаете из естественного языка язык программирования.
Скорее что-то среднее.
Так вы хотите оперировать словами естественного языка (что, в общем-то, делает большая часть языков программирования), или естественным языком?
Они не предназначены одновременно и для выполнения кода и для передачи информации. Мне нужна дополнительная коммуникативная функция, свойственная для ЕЯ. Чем ближе к естественному, тем лучше, но можно выбрать и что-то промежуточное.
Скорее что-то среднее.

То есть ни то, ни другое.

Они не предназначены одновременно и для выполнения кода и для передачи информации.

Это почему еще? AST — это информация в чистом виде.
То есть ни то, ни другое.
Или и то и другое. Это как вам угодно.

Это почему еще? AST — это информация в чистом виде.
Ну так дерево приходится и мне строить, для каждой инструкции. Но уже после передачи ее через канал коммуникации, а не до. Домохозяйка не будет этим заниматься (оборачивать координаты посудного шкафа в XML или JSON), пытаясь объяснить роботу куда складывать помытую посуду.
Ну так дерево приходится и мне строить, для каждой инструкции. Но уже после передачи ее через канал коммуникации, а не до.

А почему вы думаете, что у языков программирования это иначе?

Домохозяйка не будет этим заниматься (оборачивать координаты посудного шкафа в XML или JSON),

Ни XML, ни JSON не являются языками программирования. При чем тут это?
А почему вы думаете, что у языков программирования это иначе?
Я так не думаю, всем приходится строить дерево. Я просто не понял к чему вы упомянули про AST

Ни XML, ни JSON не являются языками программирования. При чем тут это?
Тогда опять, при чем был AST. Хотя, не важно.

Давайте так. Есть механизм, есть канал коммуникации, есть человек (среднестатистический, не програмист). Механизм обладает минимальным набором поведенческих алгоритмов и способен понимать некоторый язык через канал коммуникации (скажем пока текстовый). Задача человека, на основе уже заложенного набора алгоритмов (используя некий язык) расширить (обучить) функциональные возможности механизма в процессе коммуникации. Желательно чтобы человек при этом не оперировал непосредственно объектами кода (именами переменных, структур, процедур..), а оперировал более абстрактными объектами. Мне интересна только такая модель, ее и пытаюсь изучать. Все что за рамками — оффтоп.
Я так не думаю, всем приходится строить дерево. Я просто не понял к чему вы упомянули про AST

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

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

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

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

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

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

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

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

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

Дело не в инструкциях как таковых, а в структуре языке.

Если что-то системе не ясно, она всегда может спросить.

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

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

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

От этого никакой ЯП не застрахован, иначе отладчиков бы не существовало.

А для этого уже нужна квалификация оператора.
Угу, и тем самым превратили естественный язык в язык программирования с именованными аргументами методов.
Программирования и обмена информацией, что важно. ЯП — для программирования, ЕЯ — для обмена информацией. Тут получилось пересечение свойств, что и требуется.
Мы уже выяснили, что язык программирования вполне может быть языком обмена информацией, поэтому ничего нового не произошло.
И процесс написания кода действительно похож на классический, но из-за того, что нет конструкций условных переходов и циклов он все таки отличается, и процесс этот довольно увлекательный. Пока приходится заниматься стандартными вещами. В планах на ближайшее будущее создание отладчика.
И процесс написания кода действительно похож на классический, но из-за того, что нет конструкций условных переходов и циклов он все таки отличается, и процесс этот довольно увлекательный.

Увлекательность — хорошее качество для игры, а не для системы программирования.
Звучит, как аксиома. Не согласен.
Это мое личное мнение. Я предпочитаю, чтобы увлекательной была задача, а не инструменты, которые ее решают.
Пример кода в видео выглядит гораздо сложнее кода на обычных ЯП…

каждая инструкция однозначно отражает намерение разработчика, ее написавшего

Слово «есть» можно интерпретировать как прием пищи. Не факт, что стоит разбивать термин «солнечная система». Стоит ли разбивать термин «атом водорода» тоже наверное зависит от ситуации… Т.е. язык получается не очень однозначный.

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

Зато есть условия, которые дают тот же эффект.
Зато есть условия, которые дают тот же эффект.

Так и есть. Создание блока с инстукциями описывающими условия предполагается автоматизировать. Есть интересные мысли, но пока не готовые к изложению.
Создание блока с инстукциями описывающими условия предполагается автоматизировать.

На основании каких входных данных?
На основании каких входных данных?
Это тема для отдельной статьи, пожалуй. Но если кратко, то у триггеров, из которых состоят условия будут символические имена, даже не имена, а конструкции, выражаемые предложением. Поиск процедуры, код которой нужно править будет выполнятся ассоциативно, на основе набора символических имен.
Например, мы хотим запросить (и изменить ее код) у системы процедуру, которая вызывается в ситуции (из примера на видео), когда (в этой ситуации нужно будет изменить направление движения змейки):
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля
Можно описать эти символические имена на языке с валентностями и передать системе, на что она должна ассоциативно найти процедуру и вернуть ее текст для правки. Если процедура для такой ситуации не предусмотрена, она будет создана, попутно будут созданы необходимые условия. Это может позволить автоматически давать имена (технические) переменным в коде, триггерам, условиям, процедурам. Т.е. человек возможно не будет оперировать объектами кода в привычном понимании. Отвечать на вопросы я пока не готов. Реализация этого всего дело не близкого будущего, да и к текущей теме не относится.
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля

Вот же они, ваши входные данные. И они же и есть условия.

PS

match state with
| (currentSection, direction, headPosition)
    when (currentSection |> isHead)
    and (direction |> isDown)
    and (headPosition |> isAtLowestBound)
    -> ...
Ну да. Вот теперь наглядно сравните два этих куска кода. Интенциональность какого из них выше.
Одинакова.
И не сомневался.
И плюс к тому, первый кусок теоретически способен программировать действия машины без доступа к коду. Второй даже теоретически на это не способен.
Я не понимаю, что вы имеете в виду под «первый кусок способен программировать». Программирует не кусок, программирует человек.
В моём представлении «интенциональность» программирования не имеет прямой связи с естественным языком. Это способ формулировки программ, в котором приоритет уделяется смыслу описываемых действий, а выбор конкретного способа осуществления по мере возможности отдаётся на откуп машине. Скажем, вызов функции sort вместо вписывания пары циклов «пузырька» повышает интенциональность. Такие программы легче для понимания, а формализованный анализ и поиск ошибок забирается на более высокий уровень абстракции, что повышает надёжность.
Нетрудно заметить, что факт использования естественного языка сам по себе не гарантирует какой-то высшей степени интенциональности: на естественном языке легко можно наформулировать такой ереси, что волосы дыбом встанут, или же просто растекаться мыслью по древу, болтаясь вокруг основной сути. Для семантически однозначных программ нужен семантически однозначный язык, будь то ассемблер, питон или ыфкуиль.
Скажем, вызов функции sort вместо вписывания пары циклов «пузырька» повышает интенциональность.

Кстати, да.

SELECT FROM Authors WHERE Name CONTAINS 'Gaiman'


Прекрасно выражает интент разработчика, разве нет?

(а то, что там происходит под капотом — уже другой вопрос совершенно)
Выражает. SQL очень даже интенциональный и в его нише другого не надо.
Есть у меня пара старых добрых запросов, где уже даже я, как автор, не до конца улавливаю свои первоначальные «интенции» :) Хорошо, что СУБД не переспрашивает, что конкретно я имел в виду.
Совершенно верно: выражает, понятно, формализованно. SQL ведь делался как раз с этим прицелом. Тем не менее, какой-нибудь трёхэтажный составной запрос с маловразумительными именами таблиц и полей, коих немало можно накопать на The Daily WTF, намекает нам, что даже на таком превосходном и продуманном языке степень интенциональности может очень сильно варьироваться и в первую очередь зависит от прикладываемых разработчиком усилий.
Где-нибудь можно посмотреть весь листинг программы из видео?
Вы знаете, простой заменой регулярками из этой программы можно получить валидный код на PHP. Это значит, что ваша программа вполне себе императивна, и замена "=" на «устанавливать» не дает никаких преимуществ. К тому же абстракция протекает, что выражается в виде технической конструкции для языка Python «преобразовывать (? что элемент? как-что число,? во-что Temp? как-что буква).». У вас получился просто еще один язык программирования, никаким дальнейшим развитием языка императивность не исправить.

Если кому интересно
Заменяем, правим начало и конец, добавляем переводы строк, добавляем обвязку для запуска. При реализации рантайма по-быстрому «в лоб» происходит зацикливание в процедуре СP001 (триггер на изменение ListIterator) на строчке «set_value($ListIterator, 'значение', $ListIterator['значение'] + 1);». После добавления флага для запрещения срабатывания триггеров внутри триггеров программа выдает строку «CLR[13] SET[14] INIT[10:10] SET[A1] SET[A2] SET[A3] REFR[] ».

регулярные выражения
заменять в notepad++ или через javascript
^(\t*)создавать \?что \(=(.+) \?что иметь \?что имя \?какой (.+)\)\.\s*$
$1$GLOBALS['$3'] = ['имя' => '$3', 'значение' => [null]]; $$$3 = &$GLOBALS['$3']; $$$2 = &$$$3;


^(\t*)добавлять \?что (.+) \?чего (.+)\.\s*$
$1$$$3['значение'][] = null; $$$2 = &$$$3['значение'][count\($$$3['значение']\) - 1];


^(\t*)использовать \?что ([^\s\(\)]+) \(\?чего (.+), \?какой (\d+)\)\.\s*$
$1$$$2 = &$$$3['значение'][$4];


^(\t*)использовать \?что ([^\s\(\)]+) \(\?чего (.+), \?какой ([^\s\(\)]+)\)\.\s*$
$1$$$2 = &$$$3['значение'][$$$4['значение']];


элемент \(\?чего ([^\s\(\)]+), \?какой ([\d]+)\)
$$$1['значение'][$2]


элемент \(\?чего ([^\s\(\)]+), \?какой ([\w]+)\)
$$$1['значение'][$$$2['значение']]


^(\t*)устанавливать \?что (.+) \(\?чего (.+), \?какой (\d+)\)\.\s*$
$1set_value\($$$3, '$2', $4\);


^(\t*)устанавливать \?что (.+) \(\?чего (.+), \?какой (.+)\)\.\s*$
$1set_value\($$$3, '$2', $$$4['значение']\);


"\['значение'\]
"


выполнять \?что \(=процедура \?что иметь \?что имя \?какой Snake.(.+)\)\.
$1\(\);


\\"
"


^(\t*)регистрировать \?что ([^\s\(\)]+) \(\?на-что ([^\s\(\)]+), \?для-чего ([^\s\(\)]+)\)\.\s*$
$1unset\($$$2\); register\($$$2, '$3', $$$4\);


^(\t*)регистрировать \?что ([^\s\(\)]+) \(\?какой (.+), \?на-что ([^\s\(\)]+) \?какой (.+), \?для-чего (.+)\)\.\s*$
$1unset\($$$2\); register_ex\($$$2, $3, '$4', $5, $$$6\);


^(\t*)присоединять \(\?что ([^\s\(\)]+), \?к-чему ([^\s\(\)]+)\)\.\s*$
$1attach\($$$2, '$3'\);


^(\t*)печатать \?что значение \?какой (.+)\.\s*$
$1echo $2;


^(\t*)печатать \?что ([^\s\(\)]+) \?чего (.+)\.\s*$
$1echo $$$3['$2'];


\$\$
$


^(\t*)преобразовывать \(\?что (.+) \?как-что (.+), \?во-что (.+) \?как-что буква\)\.\s*$
$1$$$4 = $$$2;


^(\t*)увеличивать \(\?что (.+) \?чего (.+), \?на-сколько (\d+)\)\.\s*$
$1set_value\($$$3, '$2', $$$3['$2'] + $4\);


^(\t*)уменьшать \(\?что (.+) \?чего (.+), \?на-сколько (\d+)\)\.\s*$
$1set_value\($$$3, '$2', $$$3['$2'] - $4\);



\$\$
$


^(\t*)процедура (.+)\s*$
$1}\n\n$1function $2\(\)\n$1{\n\t\tforeach \($GLOBALS as $key => $value\) { $$$$key = &$GLOBALS[$key]; }\n


\$"
"


\#
//


код
<?php
    global $triggers, $allow_triggers;
    $triggers = [];
    $allow_triggers = true;


    function register(&$trigger, $type, &$variable)
    {
        global $triggers;

        $trigger = [
            'type' => $type,
            'reference' => &$variable,
            'property' => 'значение',
            'const_value' => null,
            'conditions' => [],
        ];

        $triggers[] = &$trigger;
    }

    function register_ex(&$trigger, $type, $property, $const_value, &$variable)
    {
        global $triggers;

        $trigger = [
            'type' => $type,
            'reference' => &$variable,
            'property' => $property,
            'const_value' => $const_value,
            'conditions' => [],
        ];

        $triggers[] = &$trigger;
    }

    function attach(&$trigger, $condition_name)
    {
        $trigger['conditions'][] = $condition_name;
    }

    function ref_equals(&$a, &$b)
    {
        $t = $a;

        $a = 1;
        $eq1 = ($b === $a);
        $a = 2;
        $eq2 = ($b === $a);

        $a = $t;
        return ($eq1 && $eq2);
    }

    function process_triggers(&$variable, $old_value, $new_value)
    {
        global $triggers, $allow_triggers;

        if (!isset($variable['имя'])) return;

        if (!$allow_triggers) return;
        $allow_triggers = false;

        $handlers = [];
        foreach ($triggers as $trigger) {
            if (!ref_equals($trigger['reference'], $variable)) continue;

            if (
                   $trigger['type'] == 'изменение' && $old_value != $new_value
                || $trigger['type'] == '==' && $new_value == $trigger['const_value']
                || $trigger['type'] == '!=' && $new_value != $trigger['const_value']
            )
            {
                foreach ($trigger['conditions'] as $condition_name) {
                    if (!isset($GLOBALS[$condition_name])) continue;

                    $condition = $GLOBALS[$condition_name];
                    $handlers[] = [
                        'обработчик' => $condition['обработчик'],
                        'приоритет' => isset($condition['приоритет']) ? $condition['приоритет'] : 0,
                    ];
                }

                if (isset($trigger['обработчик']) && isset($trigger['приоритет'])) {
                    $handlers[] = [
                        'обработчик' => $trigger['обработчик'],
                        'приоритет' => isset($trigger['приоритет']) ? $trigger['приоритет'] : 0,
                    ];
                }
            }
        }

        usort($handlers, function($a, $b) {
            if ($a['приоритет'] == $b['приоритет']) return 0;
            return ($a['приоритет'] > $b['приоритет'] ? -1 : 1);
        });

        foreach ($handlers as $handler) {
            eval($handler['обработчик']);
        }

        $allow_triggers = true;
    }

    function set_value(&$variable, $property, $new_value)
    {
        $old_value = isset($variable[$property]) ? $variable[$property] : null;
        $variable[$property] = $new_value;

        process_triggers($variable, $old_value, $new_value);
    }




    function Init()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Инициализация при загрузке модуля
        $GLOBALS['XList'] = ['имя' => 'XList', 'значение' => [null]]; $XList = &$GLOBALS['XList']; $список = &$XList;
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 1);
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 1);
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 1);

        $GLOBALS['YList'] = ['имя' => 'YList', 'значение' => [null]]; $YList = &$GLOBALS['YList']; $список = &$YList;
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 1);
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 2);
        $список['значение'][] = null; $элемент = &$список['значение'][count($список['значение']) - 1];
        set_value($элемент, 'значение', 3);

        $GLOBALS['SnakeLength'] = ['имя' => 'SnakeLength', 'значение' => [null]]; $SnakeLength = &$GLOBALS['SnakeLength']; $поле = &$SnakeLength;
        set_value($поле, 'значение', 3);

        $GLOBALS['Temp'] = ['имя' => 'Temp', 'значение' => [null]]; $Temp = &$GLOBALS['Temp']; $поле = &$Temp;
        $GLOBALS['ListIterator'] = ['имя' => 'ListIterator', 'значение' => [null]]; $ListIterator = &$GLOBALS['ListIterator']; $поле = &$ListIterator;

        $GLOBALS['C1'] = ['имя' => 'C1', 'значение' => [null]]; $C1 = &$GLOBALS['C1']; $условие = &$C1;
        set_value($условие, 'обработчик', "СP001();");
        set_value($условие, 'приоритет', 3);

        $GLOBALS['C2'] = ['имя' => 'C2', 'значение' => [null]]; $C2 = &$GLOBALS['C2']; $условие = &$C2;
        set_value($условие, 'обработчик', "СP002();");
        set_value($условие, 'приоритет', 2);

        $GLOBALS['C3'] = ['имя' => 'C3', 'значение' => [null]]; $C3 = &$GLOBALS['C3']; $условие = &$C3;
        set_value($условие, 'обработчик', "СP003();");
        set_value($условие, 'приоритет', 2);

        $GLOBALS['C4'] = ['имя' => 'C4', 'значение' => [null]]; $C4 = &$GLOBALS['C4']; $условие = &$C4;
        set_value($условие, 'обработчик', "СP004();");
        set_value($условие, 'приоритет', 2);

        $GLOBALS['C5'] = ['имя' => 'C5', 'значение' => [null]]; $C5 = &$GLOBALS['C5']; $условие = &$C5;
        set_value($условие, 'обработчик', "СP005();");
        set_value($условие, 'приоритет', 2);

        $GLOBALS['C6'] = ['имя' => 'C6', 'значение' => [null]]; $C6 = &$GLOBALS['C6']; $условие = &$C6;
        set_value($условие, 'обработчик', "СP006();");

        $GLOBALS['C7'] = ['имя' => 'C7', 'значение' => [null]]; $C7 = &$GLOBALS['C7']; $условие = &$C7;
        set_value($условие, 'обработчик', "СP007();");

        $GLOBALS['C8'] = ['имя' => 'C8', 'значение' => [null]]; $C8 = &$GLOBALS['C8']; $условие = &$C8;
        set_value($условие, 'обработчик', "СP008();");

        $GLOBALS['C9'] = ['имя' => 'C9', 'значение' => [null]]; $C9 = &$GLOBALS['C9']; $условие = &$C9;
        set_value($условие, 'обработчик', "СP009();");

        unset($триггер); register($триггер, 'изменение', $поле);
        attach($триггер, 'C1');

        unset($триггер); register_ex($триггер, "!=", 'значение', 3, $поле);
        attach($триггер, 'C1');

        unset($триггер); register_ex($триггер, "==", 'значение', 1, $поле);
        set_value($триггер, 'обработчик', "TP001();");
        set_value($триггер, 'приоритет', 1);

        unset($триггер); register_ex($триггер, "==", 'значение', 3, $поле);
        set_value($триггер, 'обработчик', "TP002();");
        set_value($триггер, 'приоритет', 3);

        attach($триггер, 'C2');
        attach($триггер, 'C3');
        attach($триггер, 'C4');
        attach($триггер, 'C5');
        attach($триггер, 'C6');
        attach($триггер, 'C7');
        attach($триггер, 'C8');
        attach($триггер, 'C9');

        $GLOBALS['Direction'] = ['имя' => 'Direction', 'значение' => [null]]; $Direction = &$GLOBALS['Direction']; $поле = &$Direction;

        unset($триггер); register_ex($триггер, "==", 'значение', 1, $поле);
        attach($триггер, 'C2');
        attach($триггер, 'C6');

        unset($триггер); register_ex($триггер, "==", 'значение', 2, $поле);
        attach($триггер, 'C3');
        attach($триггер, 'C8');

        unset($триггер); register_ex($триггер, "==", 'значение', 3, $поле);
        attach($триггер, 'C4');
        attach($триггер, 'C9');

        unset($триггер); register_ex($триггер, "==", 'значение', 4, $поле);
        attach($триггер, 'C5');
        attach($триггер, 'C7');

        unset($триггер); register_ex($триггер, "==", 'значение', 1, $YList['значение'][3]);
        attach($триггер, 'C8');

        unset($триггер); register_ex($триггер, "==", 'значение', 10, $YList['значение'][3]);
        attach($триггер, 'C6');

        unset($триггер); register_ex($триггер, "==", 'значение', 1, $XList['значение'][3]);
        attach($триггер, 'C9');

        unset($триггер); register_ex($триггер, "==", 'значение', 10, $XList['значение'][3]);
        attach($триггер, 'C7');

        set_value($ListIterator, 'значение', 1);
        set_value($Direction, 'значение', 1);

        echo "INIT[10:10]\n";
        echo "SET[A1]\n";
        echo "SET[A2]\n";
        echo "SET[A3]\n";
        echo "REFR[]\n";
    }

    function TP001()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Триггер ListIterator==1
        echo "CLR[";
        $элемент = &$XList['значение'][1];
        $Temp = $элемент;
        echo $Temp['значение'];
        $элемент = &$YList['значение'][$ListIterator['значение']];
        echo $элемент['значение'];
        echo "]\n";
    }

    function TP002()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Триггер ListIterator==3
        set_value($ListIterator, 'значение', 1);
        echo "REFR[]\n";
    }

    function СP001()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator, ListIterator!=3)
        set_value($Temp, 'значение', $ListIterator['значение']);
        set_value($Temp, 'значение', $Temp['значение'] + 1);
        $элемент = &$XList['значение'][$Temp['значение']];
        set_value($XList['значение'][$ListIterator['значение']], 'значение', $элемент['значение']);
        $элемент = &$YList['значение'][$Temp['значение']];
        set_value($YList['значение'][$ListIterator['значение']], 'значение', $элемент['значение']);
        set_value($ListIterator, 'значение', $ListIterator['значение'] + 1);
    }

    function СP002()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==1)
        $элемент = &$XList['значение'][$ListIterator['значение']];
        $Temp = $элемент;
        set_value($YList['значение'][$ListIterator['значение']], 'значение', $YList['значение'][$ListIterator['значение']]['значение'] + 1);
        echo "SET[";
        echo $Temp['значение'];
        echo $YList['значение'][$ListIterator['значение']]['значение'];
        echo "]\n";
    }

    function СP003()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==1)
        $элемент = &$XList['значение'][$ListIterator['значение']];
        $Temp = $элемент;
        set_value($YList['значение'][$ListIterator['значение']], 'значение', $YList['значение'][$ListIterator['значение']]['значение'] - 1);
        echo "SET[";
        echo $Temp['значение'];
        echo $YList['значение'][$ListIterator['значение']]['значение'];
        echo "]\n";
    }

    function СP004()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==4)
        set_value($XList['значение'][$ListIterator['значение']], 'значение', $XList['значение'][$ListIterator['значение']]['значение'] - 1);
        $элемент = &$XList['значение'][$ListIterator['значение']];
        $Temp = $элемент;
        echo "SET[";
        echo $Temp['значение'];
        echo $YList['значение'][$ListIterator['значение']]['значение'];
        echo "]\n";
    }

    function СP005()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==4)
        set_value($XList['значение'][$ListIterator['значение']], 'значение', $XList['значение'][$ListIterator['значение']]['значение'] + 1);
        $элемент = &$XList['значение'][$ListIterator['значение']];
        $Temp = $элемент;
        echo "SET[";
        echo $Temp['значение'];
        echo $YList['значение'][$ListIterator['значение']]['значение'];
        echo "]\n";
    }

    function СP006()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==1, Y[3]==10)
        set_value($Direction, 'значение', 4);
    }

    function СP007()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==4, X[3]==10)
        set_value($Direction, 'значение', 2);
    }

    function СP008()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==2, Y[3]==1)
        set_value($Direction, 'значение', 3);
    }

    function СP009()
    {
        foreach ($GLOBALS as $key => $value) { $$key = &$GLOBALS[$key]; }

        // Условие (ListIterator==3, Direction==3, X[3]==1)
        set_value($Direction, 'значение', 1);
    }


    Init();



Я не против "=", как и не против PHP. Но он не обладает свойством коммуникативности. Задача была не избавиться от императивности, а скорее наоборот, сохранить ее и добавить к ней коммуникативности. Чтобы язык и выполняться мог и информацию переносить.
После добавления флага для запрещения срабатывания триггеров внутри триггеров
Это вы правильно сделали.
программа выдает строку «CLR[13] SET[14] INIT[10:10] SET[A1] SET[A2] SET[A3] REFR[] ».
Должно быть так:
INIT[10:10] — определяем игровое поле для змейки 10х10 клеток
SET[A1] SET[A2] SET[A3] — Устанавливаем «звездочку» в ячейки A1, A2, A3
REFR[] — обновление содержимого экрана
CLR[A1] — удаляем «звездочку» из ячейки A1
SET[A4] — устанавливаем звездочку в ячейку А4
REFR[] — обновление содержимого экрана
CLR[A2] — удаляем «звездочку» из ячейки A2
SET[A5] — устанавливаем звездочку в ячейку А5
REFR[] — обновление содержимого экрана
CLR[A3] — удаляем «звездочку» из ячейки A3
SET[A6] — устанавливаем звездочку в ячейку А6
REFR[] — обновление содержимого экрана
и т.д. пока змейка не дойдет до грани поля
Эти комманды записываются в пайп, из которого читает другая программа-терминал, отображающая эти команды как бегающую змейку.

У вас порядок инструкций попутался т.к. некоторые триггеры и условия могут активироваться одновременно, но их обработчики не всегда могут вызываться в произвольном порядке, тут есть правила, которые я уже выявил. Таким образом, обработчикам, присваиваются приоритеты, чтобы в спорном случае интерпретатор знал, какой обработчик нужно вызывать первым. В коде из примера приоритеты заданы явно инструкцией «устанавливать? что приоритет (? чего X,? какой Y).» Хотя в реальной работе они будут рассчитываться интерпертатором (сейчас я по установленному алгоритму определяю приоритеты расчетами в экселе)
Задача была не избавиться от императивности, а скорее наоборот, сохранить ее

Тогда вы не сможете «программировать через описание». Да с интенциональностью это плохо сочетается.

Чтобы язык и выполняться мог и информацию переносить.

Для переноса информации ничто из того, что вы используете, не обязательно (и не нужно).

Тогда вы не сможете «программировать через описание». Да с интенциональностью это плохо сочетается.
Почему не смогу?

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

Потому что описание (в обычном его понимании) — это декларативное, а не императивное программирование.

Что по вашему мнению я должен использовать вместо всего этого?

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

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

Тогда оно перестает быть описанием.

Списком из чего?

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

Тот же, кто заполняет ваше «дерево».

Непрограммист сможет это делать?

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

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

Я тут верну вам ваш аргумент: это для вас не проблема. А для «обычного человека» может быть.

Ну и да, если это для человека не проблема, то и заполнение списка для человека не проблема.
Приоритеты учитываются, ошибка в другом, но суть не в этом. Я просто хотел показать, что вы не ушли от использования объектов кода. То, что вы условие (ListIterator == 3 && Direction == 1) обозначили одной переменной C2, не означает, что вы от нее избавились. И программа все равно требует знаний в области программирования, несмотря на то, что часть переменных названа русскими буквами.

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

Кстати, а зачем вы сделали отдельный интерпретатор? Не потому ли, что с такой системой триггеров очистить участок экрана AxB это не самая простая задача?)
Зачем показывать промежуточные примеры, да еще и требующие отдельного интерпретатора команд?
Чтобы периодически получать фидбэк. Обсуждение обычно помогает лучше понять.
Спасибо за статью.
Я вижу две основных проблемы с естественными языками:
1. Они неоднозначны, т.е., допускают возможность различного трактования в зависимости от массы факторов, как внутренних, так и внешних. «ДАО, которое может быть выражено словами, не есть постоянное дао.»
2. Они многословны и громоздки, по сравнению с отточенными формальными языками программирования (или с языком математических формул, например).
Именно поэтому я предпочту строго формализованный язык программирования естественному.

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

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

>Можно доопределить, что при одинаковых вопросах первым идёт субъект, а вторым — объект
если уж фиксировать порядок, стоит задуматься, то почему бы не хранить фреймы в таблицах, с колонками-валентностями, например, в CSV-формате с разделителем «пробел», получим просто в несколько пробелов там, где не все валентности заданы.
Когда-то даже пытался писать базу данных на этой идее, только вместо одного ключевого слова можно использовать любое сочетание.

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

А почему бы не пойти еще дальше: зачем нам ключевое слово? зачем валентности? Предлагаю язык bundle, предложения-твиты(не совсем естественный язык :)).
Может кто не видел статью.
Также язык сценариев warcraft 3 тоже довольно человекочитаем.
Не совсем понял, как ваша идея соотносится с литературным программированием. С другой стороны, в интенциональном программировании нет такого упора на естественный язык: как вы относитесь к тому, чтобы словами описывать цвет и размер кнопок, чуть правее поля ввода имени пользователя словами?
Также язык сценариев warcraft 3 тоже довольно человекочитаем.

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

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

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

Обучить правилам или научить играть в игру?
Можете считать, что это одно и то же, т.к. теория без практики не особо полезна
Вообще-то, это совершенно разные вещи. Прочитав правила, человек может играть в игру (если они полны и непротиворечивы). Но что интереснее, он после этого может начать строить выигрышные стратегии (то есть учиться играть), причем как с внешним обучением, так и без него.
Тема призрачного СИИ далека от моих интересов.
Без СИИ то, что вы описываете (в полной форме), невозможно.
Возможно. Посмотрим
обучение компьютера играть в игры

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

Например, во всех играх есть игроки, их может быть определенное количество. Они могут играть разные роли. В игре могут быть вспомогательные объекты (доска, фишки, фигуры, карты, кубики). Игроки в определенной последовательности что-то делают. Делают с объектами (кидают кубик) или без объектов (загадывают число, говорят что-то другим игрокам).

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

Машина может либо узнавать по вопросам игры, которые она знает. Либо может узнавать у человека новые игры.

Есть готовый софт для создания разных типовых игр www.gambit-project.org
Есть теория, та же теория игр.

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

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

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

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

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

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

При этом, впрочем, вид глагола к этому не имеет никакого отношения. «Двигатель запущен» — это одновременно событие («двигатель был запущен в 15:00») и состояние («двигатель запущен и не был остановлен»), при этом это же состояние можно выразить глаголом другого вида («двигатель работает»).

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

>«Двигатель запущен» — это одновременно событие и состояние
если правильно понял, то именно это и понимает автор под событиями

с причастиями вы меня подловили :)
если правильно понял, то именно это и понимает автор под событиями

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

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

Во время обсуждения прошлой статьи с ув. lair стало понятно, что кроме событий есть еще и состояния. Оба эти термина объедены в понятие триггер. Он имеет 2 устойчивых состояния: активирован и деактивирован. Триггер состояния может быть активным долгое время, триггер события деактивируется после вызова его обработчика. Несколько триггеров могут быть объединены в условие, которое активируется тогда, когда все его триггеры активированы.
В таком случае, может оказаться удобно рассматривать триггеры не как физические состояния, а как знание системы об этих состояниях.
Не «двигатель работает», а «известно, что двигатель работает».
Поскольку знания устаревают, то их триггеры можно сбрасывать по таймауту.
Но тогда может оказаться, что триггер не установлен(например при инициализации системы), а двигатель работает.
Значит, когда триггер сброшен, а он входит в «ситуацию», нужно проверить какие-то условия. Если ситуация желаемая, то кроме проверки можно предпринять действия, направленные на выполнение условий триггера(как в makefile).
Тогда весь поток управления — не более чем рекоммендуемая последовательность проверок, которую можно заменить на систему приоритетов.

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

Вы-таки собираетесь решать проблему останова?
>Не во всяком языке есть виды глаголов.
Приведите пожалуйста пример, мне просто интересно.
Даже в китайском есть:
Прошедшее завершенное время глагола обозначает действие, которое было совершено в прошлом. Для того, чтобы показать завершенность действия к глаголу присоединяется суффикс 了 le
Приведите пожалуйста пример, мне просто интересно.

Английский, испанский (чуть ли не все романские, на самом деле). В них есть завершенные (совершенные) времена, но нет деления глаголов на совершенные и несовершенные.
это уже детали: есть doing-done, stopping-stoped…
Эти детали и отличают понимание языка. В русском вы можете определить вид глагола по его неопределенной форме, а в английском — нет. Более того, глагол read принесет вам столько счастья…
Допустим, у автора получится. И что это изменит? Сложность предметной области от этого никуда не пропадёт.
Будут описывать её не в миллионах строк программного кода, а миллионах строк книжных томов.

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

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

При этом легко посадить противоречие, приводящее к неопределённому поведению (которая машина, в соответствии с теоремой Гёделя, сама найти не может, всё вылезет на тестах и эксплуатации)
В ваших словах есть доля правды, если вы читали прошлую статью и осознали плюсы ее подхода. Для этого и разрабатывается интерпретатор, чтобы подтвердить, или опровергнуть.
В принципе, ситуационное программирование интересно само по себе, чего не скажешь про программирование на естественном языке. Но в паре они могут позволить выполнять программирование (изменение поведения) объяснением, без оперирования объектами кода. Подчеркиваю, не позволят, а могут позволить. Это предмет исследования.
Но в паре...
предлагаю термин широкое программирование(wide programming), а вместе с ним еще парочку: идентификатор ситуации, событийный адрес, ассоциативный адрес
Уточню, что событие и ситуация это не одно и то же. Событие и состояние это триггер. Ситуация это условие — группа триггеров.
тогда:
событийный адрес — это дерево триггеров, приводящее к ситуации
идентификатор ситуации — множество условий, однозначно эту ситуацию идентифицирующее
Понятие «событийный адрес» не нужно.
Человек описывает системе ситуацию через набор триггеров:
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля
Система сама ищет обработчик этой ситуации. Если его нет — создает.
Событие это один триггер, как и состояние это один триггер.
Ситуация (условие) это совокупность триггеров (и вложенных ситуаций). Т.е. ситуации (условия) иерархичны. Вложение одних условий в другие пока не реализовано, но оно необходимо.
Ситуация в понимании человека = условие в интерпретаторе.
Понятие «событийный адрес» не нужно.
это пока вы не добавите к валентостям «зачем?» :)

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

Угу. А как определить, какая ситуация ему нужна? Что важнее — как определить, что изменится, когда он внесет свои изменения?
Угу. А как определить, какая ситуация ему нужна?
Процитирую то, что уже писал выше, может быть на этот раз вы прочтете все.
«Это тема для отдельной статьи, пожалуй. Но если кратко, то у триггеров, из которых состоят условия будут символические имена, даже не имена, а конструкции, выражаемые предложением. Поиск процедуры, код которой нужно править будет выполнятся ассоциативно, на основе набора символических имен.
Например, мы хотим запросить (и изменить ее код) у системы процедуру, которая вызывается в ситуции (из примера на видео), когда (в этой ситуации нужно будет изменить направление движения змейки):
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля
Можно описать эти символические имена на языке с валентностями и передать системе, на что она должна ассоциативно найти процедуру и вернуть ее текст для правки. Если процедура для такой ситуации не предусмотрена, она будет создана, попутно будут созданы необходимые условия. Это может позволить автоматически давать имена (технические) переменным в коде, триггерам, условиям, процедурам. Т.е. человек возможно не будет оперировать объектами кода в привычном понимании. Отвечать на вопросы я пока не готов. Реализация этого всего дело не близкого будущего, да и к текущей теме не относится.»

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

Но откуда мы возьмем набор входных условий?

Есть и более занятный вопрос: предположим, в системе уже определена реакция на состояние «направление движения — вниз». Теперь мы хотим определить реакцию на состояние «направление движения — вниз, и позиция в нижнем ряду». Как эти две реакции будут друг с другом соотноситься?

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

Вот как раз как разработчик я очень хорошо знаю, что в любой сколь-либо сложной системе изменение может проявиться не сразу, и неочевидным образом. Иными словами, чем сложнее система, тем, при прочих равных, вероятнее в ней эффект бабочки.
Но откуда мы возьмем набор входных условий?
Для этого и нужен естественный язык. Набор входных условий описывает на нем человек:
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля
После чего он указывает набор инструкций для выполнения в этой ситуации.

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

Вы сейчас говорите о программировании в классическом понимании, когда тестировщик понятия не имеет, что вы исправили в коде, а если и имеет, то поверхностное.
А давайте отойдем от модели обучения с учителем и предположим, что все программы будут создаваться на основе ситуационного подхода. Вы, как программист, изменивший набор ситуаций (условий) можете предоставить список этих условий тестировщику. Если он все их протестирует, то откуда возникнет эффект бабочки?
Хотя, в некоторой степени вы конечно правы, и ошибка может возникнуть всегда, но ситуационный подход сильно уменьшает ее возникновение, это же очевидно.
Для этого и нужен естественный язык. Набор входных условий описывает на нем человек:
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля

А откуда он их возьмет?

Если он все их протестирует, то откуда возникнет эффект бабочки?

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

Более того, внесенное вами поведение может провоцировать новые ситуации и новые реакции, и как это протестировать?

Вы совершенно зря проигнорировали мой пример с пересекающимися условиями.
А откуда он их возьмет?
Из головы.

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

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

Угу. В этом и будет основная сложность.

Конечно для всех. А что неполное тестирование когда-то красило тестировщика?

Проблема в том, что вы усложняете его работу.

За одну итерацию исправления он врядли будет большим.

Вы не можете это предсказать.

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

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

Возможно случайно, как ситуации могут пересекаться?

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

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

Вот тут ваша фундаментальная ошибка.

Аналитик сказал «надо добавить обработчик вот такой ситуации». Программист сказал «ок» и добавил. Тестировщик пошел и проверил добавленный обработчик. Откуда все они узнают про то, что на одном из условий в этой ситуации висел другой обработчик, который при специфическом сочетании условий даст побочный эффект?

Регламентом.

Извините, но в «традиционном» программировании это тоже все можно сделать регламентом. Только не работает регламент. Никогда.

А про побочные эффеты мне не известно.

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

В данном случае нужно будет править одновременно 2 обработчика. Вернее перенести часть из первого во второй.

Откуда вы это знаете?

Надо будет думать, как это автоматизировать. Пока еще рано. Возможно, что автоматизировать не получиться.

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

Обработчики у них разные.

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

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

Откуда вы это знаете?
Потому что сталкивался уже с этим.

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

Да понятно, что разные, но вызывается ли первый, когда вызывается второй?
Если понятно, то это странный вопрос.

Такого быть не должно. Обработчики не пересекаются.

Во-первых, пересекаются, мы это выяснили. Во-вторых, как в таком случае обработать вот такой банальный набор требований:

(1) при каждом списании 100 рублей со счета, на связанный счет должен начисляться 1 рубль (бонусная система)
(2) раз в месяц со счета должны списываться 1000 рублей (регулярный платеж)

Такие комментарии отбивают охоту отвечать. Вы же понимаете, что то, чего нет, может появится.

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

Потому что сталкивался уже с этим.

И уже успели обобщить свой опыт на все возможные ситуации?

Возможно. Но это все равно гораздо легче, чем править линейную простыню.

О какой «линейной простыне» вы говорите?

Если понятно, то это странный вопрос.

Обработчики — разные, но их условия совпадают. По логике, должны вызываться оба. Это так, или нет?

Во-первых, пересекаются, мы это выяснили.
Когда выяснили? Они могут пересекаться только если создается новое условие.

(1) при каждом списании 100 рублей со счета, на связанный счет должен начисляться 1 рубль (бонусная система)
(2) раз в месяц со счета должны списываться 1000 рублей (регулярный платеж)
Это отдельная подпрограмма, соизмеримая со змейкой. Но она реализуема.

И сразу возникает вопрос, как вы будете бороться с возрастанием сложности в таком случае.
Модульностью

И уже успели обобщить свой опыт на все возможные ситуации
Да, пока не появились ситуации не вписывающиеся в опыт.

О какой «линейной простыне» вы говорите?
Об классическом программирование: if, for, while…

Обработчики — разные, но их условия совпадают. По логике, должны вызываться оба. Это так, или нет?
Не может быть так. У каждого условия (ситуации) свой обработчик.
Когда выяснили? Они могут пересекаться только если создается новое условие.

Могут же, этого достаточно.

Это отдельная подпрограмма, соизмеримая со змейкой. Но она реализуема.

Это же два разных условия, правильно? И два разных обработчика, так?

Об классическом программирование: if, for, while…

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

Не может быть так. У каждого условия (ситуации) свой обработчик.

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

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

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

Знаете, структурное программирование — которое избавляет от линейных простыней — давно придумали.
Структурное программирование призвано уменьшить код блока (процедуры/функции).
Ситуационное программирование призвано свести код блока к 1-2 строкам.

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

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

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

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

Ситуационное программирование призвано свести код блока к 1-2 строкам.

Что такого предлагает ситуационное программирование, что позволяет радикально уменьшить размер (семантически эквивалентного) блока кода?

Да как же у одной ситуации может быть больше одного обработчика?

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

Это два независимых правила, реализующих различные бизнес-задачи. Как следствие, SRP говорит нам, что они должны быть в разных обработчиках.

Ничего не понял.

Пример выше.

Ну конечно. Первое это триггер, у него свой обработчик. Второе это условие из двух триггеров, у этого условия свой обработчик.

Так вот, когда состояние системы удовлетворяет условиям «движение вниз и позиция в нижнем краю» — вызываются оба обработчика, или только один?

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

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

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

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

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

Вот вы и получили побочный эффект в обработчике.

Я не про семантически эквивалентный блок, а про процедуру (функцию), как блок.

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

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

Во-первых, что за понятие «подпрограмма», откуда оно внезапно взялось, вы же вроде говорили, что оператор не использует объекты из кода?
Во-вторых, если это будет один обработчик, то вы нарушаете SRP.

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

Собственно, и чем это отличается от «традиционного» программирования?

Могут и два, если у них нет общих переменных, то могу вызваться параллельно, если есть, то друг за другом.

Если два обработчика, то вы снова можете получить непредвиденные побочные эффекты.

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

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

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

Не в программе, а у себя в голове. В программу попадает алгоритм реакции на события, а не описание ситуаций.
Совершенно верно, программист транслирует естественное (для человека) описание ситуаций в неестественное — многоуровневое вложение условий. Это и отличает программиста от человека. Хотя отличие не только в этом. Отличие еще в том, что программист способен удерживать внимание на большем количестве объектов, чем непрограммист. Я решил задачу Эйнштейна за 40 минут, без ручки и бумаги, только в уме, не читая алгоритм нахождения ответа, и про сам ответ. Считаю, что на это способен любой программист с опытом. Чего не скажешь про непрограммистов.
Я же хочу решить проблему программирования без необходимости одновременно оперировать десятком уровней вложенности условий и десятками переменных.
Да, вы превращаете два уровня вложенности условий в соответствующее количество плоских условий, тем самым увеличивая их число. При этом вы забываете тот занимательный факт, что количество объектов одного уровня, воспринимаемых человеком, ограниченно, а иерархия как раз позволяет снять эту проблему.
Да, вы превращаете два уровня вложенности условий в соответствующее количество плоских условий,
тем самым увеличивая их число
Эм…
А что «эм»?

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

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

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

Банальный пример (из тех же правил): "(в некоторый момент игры) вы взяли карту. Если это карта типа а, то. Если эта карта типа б, то." Мы сначала ограничили область видимости («в некоторый момент игры вы взяли карту»), а только потом разбираем ее тип. Вот и иерархия.

Объектами кода человек вообще не будет оперировать.

А объекты кода тут ни при чем, мы обсуждаем условия и реакции.
Это неправда. Человеческий мозг прекрасно структурирует информацию — именно для того, чтобы бороться со сложностью, — и иерархия один из способов такого структурирования.
Согласен

Банальный пример (из тех же правил): "(в некоторый момент игры) вы взяли карту. Если это карта типа а, то. Если эта карта типа б, то." Мы сначала ограничили область видимости («в некоторый момент игры вы взяли карту»), а только потом разбираем ее тип. Вот и иерархия.
Но это можно представить и как линейный список:
Идет игра X
Игрок Y взял карту Z
Выбранная карта это А
(Перечень инструкций)

Идет игра X
Игрок Y взял карту Z
Выбранная карта это В
(Перечень инструкций)

Но замечание дельное, надо будет об этом думать, но точно не сейчас.
Но это можно представить и как линейный список:

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

А теперь посмотрим: вот мы представили первую взятую карту хода как контекст, и расписываем возможные условия: карта А, карта Б, карта Ц… чем это отличается от традиционной процедуры с переключателем по типам карт?
Это при классическом программировании, не при ситуационном (естественном для человека).

А почему вы считаете, что ситуационное программирование естественно для человека? В прошлой дискуссии вы так и не смогли это утверждение как-то подтвердить.
Конечно не смог, это либо понимаешь, либо нет. Для меня это очевидно. Но для прожженного программиста это может быть и неочевидно. Он же уже не может перестроиться в нормального человека с природным мышлением.
Если вы не можете объяснить то, что вам очевидно, может, оно не так и очевидно?

А чтобы избавиться от аргументов ad hominem — которые вас не красят — просто возьмите десяток правил настольных игр, написанных далеко не программистами, и обратите внимание, что они вполне укладываются во flowchart. Более того, именно flowchart — это одна из первых записей, к которым приходят люди, когда пытаются объяснить друг другу какой-то сложный процесс.
которые вас не красят
Ну я же не красна девица. Да и вообще могу вам не отвечать, как троллю. Что вобщем-то скоро и случится.
При чем тут flowchart.
При чем тут flowchart.

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

Каким именно образом?
Всему свое время.
Стоп, какие переменные, у вас же нет никаких «объектов кода», с которыми взаимодействует оператор.
Переменые будут, триггеры ведь навешиваются на значения переменных. Но принцип взаимодействия будет описан в следующих статьях. Взаимодействие через язык.
Если есть переменные, то есть и объекты кода. И весь ваш пассаж про «оператор не взаимодействует с объектами кода» теряет смысл.
Нет, не теряет. Это будет скрыто. Потерпите уж
Вооот, будет скрыто. Значит, человек будет взаимодействовать не с переменными (и, как следствие, нам все равно, какая у них область видимости). А вот какая область видимости у ваших условий?
Локальная в пределах модуля (подпрограммы).
Модуль (подпрограмма) — это тоже объект кода. Как оператор будет выбирать нужное ему условие?
Идентификатор условия (С1, С2, С3...) видим в пределах модуля. Но его символическое представление видимо глобально.
Но его символическое представление видимо глобально.

Это означает, что у вас все условия видны глобально — что, в свою очередь, возвращает нас к проблеме множества объектов в одной области видимости.
Да, но поскольку они описываются естественным (условно говоря) языком, то это не проблема
Да такая же это проблема. Все равно надо как-то различать множество объектов, которыми ты оперируешь.
Объекты разные будут
Понятно, что разные, одинаковые различать не надо. Проблема, однако же, в том, что количество разных объектов, которыми может оперировать человек, ограничено.
Под символическим представлением я подразумеваю:
1. Текущая секция змейки является головой
2. Направление движения змейки — вниз
3. Голова змейки находится в самой нижней клетке поля
Т.е. набор символических представлений триггеров (на ЕЯ).
Вернее примерно так:
(? чего змейки,? какая текущая) секция? что является? чем головой.
змейка? что движется? куда вниз.
змейки? чего голова? что находится? где клетка (? какая *самая нижняя,? чего поля).
Хабр сделал неправильную разметку. Должно быть так:
(?чего змейки, ?какая текущая) секция ?что является ?чем головой.
змейка ?что движется ?куда вниз.
змейки ?чего голова ?что находится ?где клетка (?какая *самая нижняя, ?чего поля).
У вас предметная область состоит из двух объектов — змейки и поля. А представьте, что их хотя бы сотня.

(собственно, ваши проблемы усугубятся уже тогда, когда у вас будет три змейки, из которых у двух одинаковое поведение, а у третьей — схожее, но частично отличающееся)
Возможно, но не забывайте, что основная цель проекта это обучение робота, так что врядли такая проблем возникнет.
А роботу не надо оперировать многими объектами?
А как вам идея расширить возможности обычного терминала до понимания естественной речи, вот есть даже upstart, в котором есть действие по событиям:
start on tty-added or cua-added

script
 ...
end script

Многого можно добится просто добавив множество алиасов:
xset led 3: enable keyboard indicator
xset -led 3: disable keyboard indicator
lsmod: view loaded kernel module list
ls -l somefile: view somefile permissions
chmod u=x somefile: permit owner execution somefile
Объяснение правил игры — удобный способ изменения настроек, файлов конфигурации.
А где понимание естественной речи-то взять?
это просто естественное развитие функций консоли, т.е. неизбежно.
распознавание устной речи сейчас уже не такая неподъемная задача
дальше можно взять обычный семантический анализ(возможно, с приправой из deep learning и прочего)
это просто естественное развитие функций консоли, т.е. неизбежно.

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

(ну, когда понимание естественной речи будет, конечно)
имею ввиду, управление голосом как логичное продолжение именно консольного интерфейса, а не графического или менюшного
также как жестовый интерфейс — развитие ввода с помощью мышки
программист будущего — заклинатель с волшебной палочкой :)
Я не уверен, что корректно приравнивать голосовое управление к консоли. С моей точки зрения, это сильно разные вещи.
Интересно, спасибо
вот вам еще идея: генерация regexp-а по нескольким похожим выражениям(wiki/Расстояние_Левенштейна)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории