OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 23 Апрель, 2024 15:25

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 43 ]  На страницу 1, 2, 3  След.
Автор Сообщение
 Заголовок сообщения: Сложные логические выражения
СообщениеДобавлено: Среда, 05 Апрель, 2023 13:17 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Пожалуй, всё-таки тема не исчерпана и надо записать то, что накопилось. Начало темы - в телеге, не хочу повторяться.

Дано:
Код:
IF ((rightType IS SyntaxTree.ArrayType) & (rightType(SyntaxTree.ArrayType).staticLength # 0) OR (rightType IS SyntaxTree.MathArrayType) & (rightType(SyntaxTree.MathArrayType).staticLength # 0)) &
(leftType(SyntaxTree.ArrayType).staticLength # 0) THEN


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

  • Развить в голове специализированную нейронную сеть, чтобы стало читать легко (Сергей Дурманов, видимо, так сделал, я так думаю по той причине, что он шахматист, а они именно это и делают; хотя, если подходить научно, то нужно не просто принять на веру заявление Сергея, что он легко прочитал данный однострочник, но и проверить, правильно ли он его прочитал).
  • нарисовать дерево так, чтобы было видно, где у него что. Здесь моё видение, как это должно выглядеть, на данный момент.
    Код:
    IF
           (     (rightType IS SyntaxTree.ArrayType)
               & (rightType(SyntaxTree.ArrayType).staticLength # 0)
            OR   
                 (rightType IS SyntaxTree.MathArrayType)
               & (rightType(SyntaxTree.MathArrayType).staticLength # 0)
           )
       &
           (leftType(SyntaxTree.ArrayType).staticLength # 0)
       THEN


    Хотя у других - другое видение, но третьи и ошиблись, читая другое видение. На моё видение никто не отреагировал, поэтому не могу судить о его качестве. На мой взгляд, всё ещё есть риск упустить "&" в голове выражения и ошибиться, т.к. это "&" находится слишком далеко от IF, и с этим ничего сделать в рамках данного подхода нельзя. При этом обязательно создание инструмента, который будет автоматически форматировать код в дерево по этим правилам - вручную будут ошибки.
  • префиксная форма операторов. Такая форма в лиспе, но есть она и в Mathematica. Будет что-то вроде:
    Код:
      [[&]](
         [[OR]](
              [[&]]((rightType IS SyntaxTree.ArrayType),
                      (rightType(SyntaxTree.ArrayType).staticLength # 0))
              ,
              [[&]]((rightType IS SyntaxTree.MathArrayType),
                      (rightType(SyntaxTree.MathArrayType).staticLength # 0)))
         ,
         (leftType(SyntaxTree.ArrayType).staticLength # 0))
  • решение из Перла - два комплекта логических операций с разными приоритетами - уменьшают количество скобок. В идеальном случае будет так:
    Код:
    IF
           (     rightType IS SyntaxTree.ArrayType
               [[&]] rightType(SyntaxTree.ArrayType).staticLength # 0
            [[OR]]   
                 rightType IS SyntaxTree.MathArrayType
               [[&]] rightType(SyntaxTree.MathArrayType).staticLength # 0
           )
       [[&]]
           leftType(SyntaxTree.ArrayType).staticLength # 0
       THEN

    На мой взгляд, стало лишь немногим легче.
  • рефакторинг - завести несколько логических переменных под каждое условие, тогда сами условия упростятся
  • помечать скобки разного вида, например, скобки, отграничивающие OR в выражение (a OR b) писать как ((*OR*) a OR b (*OR*)). Получится так:

    Код:
    IF ((*OR1*)(rightType IS SyntaxTree.ArrayType) & (rightType(SyntaxTree.ArrayType).staticLength # 0) OR (rightType IS SyntaxTree.MathArrayType) & (rightType(SyntaxTree.MathArrayType).staticLength # 0)(*OR1*)) &
    (leftType(SyntaxTree.ArrayType).staticLength # 0) THEN


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

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 05 Апрель, 2023 13:30 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Мне кстати понравился вариант с (*OR1*), он не пафосный, но читать сразу стало резко легче.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 05 Апрель, 2023 16:52 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1449
Откуда: Киев
Если абстрагироваться от выстраивания составных логических выражений, то конкретно это выражение по-хорошему должно было выглядеть так:
Код:
IF  (rightType(SyntaxTree.BaseArrayType).staticLength # 0)
 &  ( leftType(SyntaxTree.BaseArrayType).staticLength # 0)
THEN
Переделка кода для такой возможности должна быть простой, если нет надуманных переусложнений в работе с этим деревом. Тут пару взмахов над типами.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 05 Апрель, 2023 19:23 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1166
Код:
IF IsStaticArray(leftType) & IsStatiсOrMathArray(rightType) THEN … END

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Четверг, 06 Апрель, 2023 14:13 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Насчёт "переделывать код не надо" - это уже неправда. Пример взят из реального кода компилятора Fox из A2, в который я вношу изменения, стараясь ничего не сломать. Откуда возьмутся эти предикаты, если их не было? Их надо написать и заменить выражения на эти предикаты (при этом есть риск внести ошибку в компилятор, а это достаточно страшно). Это и есть "переделывать код". Да и то, как Вы назвали Ваши предикаты, говорит о том, что Вы не прочитали условия. Надо было бы назвать не "СтатическийМассивЛи?", а какой-нибудь "СтатическийМассивНенулевойДлиныЛи?" А на самом деле и я не знаю, о чём эти условия, я просто их нашёл, как пример заковыристых условий. Неизвестно из данного фрагмента, о чём речь. Т.е. если вот так начать слёту переделывать, может стать ещё хуже, чем было. Потому что имена, вводящие в заблуждение - это ещё хуже, чем сложно выписанные условия. И наконец, я этот вариант перечислил в пункте "рефакторинг", хотя я там написал другой вариант рефакторинга, но понятно, что внесение фрагмента кода в процедуру - это тоже рефакторинг.

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

Код:
if not а.булевоПоле and not а.другоеБулевоПоле and (поле.вызовФункции('литерал') or поле == 'литерал'):


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

Его можно было бы написать так, наверное:

Код:
if ( #AND
    not а.булевоПоле
    and not а.другоеБулевоПоле
    and ( #OR
              поле.вызовФункции('литерал') or поле == 'литерал'
           )): #OR AND

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Четверг, 06 Апрель, 2023 16:25 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1166
я даже не пытался расшифровывать ту ерунду, которая в начальном посте, мне это неинтересно. я показал рабочее решение, которое делает код чище. боитесь трогать — не трогайте, не лезьте туда, где страшно. а если хочется нормальный код — то не надо в него гадить дополнительным визуальным мусором, это читаемость совершенно не повышает. dixi.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Пятница, 07 Апрель, 2023 00:25 

Зарегистрирован: Пятница, 13 Март, 2015 16:40
Сообщения: 597
Логическое произведение инверсий - это инверсия логической суммы:
Цитата:
not а.булевоПоле and not а.другоеБулевоПоле

не будет ли читаемее:
not (а.булевоПоле or а.другоеБулевоПоле) ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Пятница, 07 Апрель, 2023 07:28 

Зарегистрирован: Пятница, 11 Январь, 2019 19:26
Сообщения: 293
Откуда: Russia
Я не держу в памяти никаких деревьев - в выражении открывающая скобка, остальные открывающие сразу закрываются в простых подвыражениях. Поэтому выражение читается элементарно и конечную закрывающую скобку найти не проблема.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Пятница, 07 Апрель, 2023 10:39 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Код:
(rightType(SyntaxTree.ArrayType).staticLength # 0)

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


Последний раз редактировалось budden Пятница, 07 Апрель, 2023 11:55, всего редактировалось 4 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Пятница, 07 Апрель, 2023 10:41 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Artyemov писал(а):
Логическое произведение инверсий - это инверсия логической суммы:
Цитата:
not а.булевоПоле and not а.другоеБулевоПоле

не будет ли читаемее:
not (а.булевоПоле or а.другоеБулевоПоле) ?

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Вторник, 11 Апрель, 2023 01:49 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Сегодня отформатировал пару условий. Пока что язык ЯОС - это всё же Активный Оберон, поэтому, думаю, будет не слишком уж неуместно помещать такие цитаты, тем более в таком отстранённом форуме:

Код:
аесли
    (закавыченЛи¿ = 0)
  и
    ((*или*) (текСимв = Ю32.Симв32КонцаТекста)
      или (текСимв = Пробел)
      или (текСимв = ТАБ)
      или (текСимв = ОткрывающаяКруглаяСкобка)
      или (текСимв = ЗакрывающаяКруглаяСкобка)(*или*)) то


И ещё один:
Код:
если   (рез # НУЛЬ)
      и ~(рез суть Ошибка)
      и (чтец.кодВозвратаПоследнейОперации # Потоки.КонецФайла) то


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Вторник, 11 Апрель, 2023 13:47 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Но в лисповом стиле это всё было бы лучше, конечно:
Код:
аесли (И (= закавыченЛи¿ 0)
             (ИЛИ (= текСимв Ю32.Симв32КонцаТекста)
                (= текСимв Пробел)
                (= текСимв ТАБ)
                (= текСимв ОткрывающаяКруглаяСкобка)
                (= текСимв ЗакрывающаяКруглаяСкобка))) то

В префиксной форме, но на Обероне, тоже ничего:
Код:
аесли И(закавыченЛи¿ = 0,
               ИЛИ(текСимв = Ю32.Симв32КонцаТекста,
                 текСимв = Пробел,
                 текСимв = ТАБ,
                 текСимв = ОткрывающаяКруглаяСкобка,
                 текСимв = ЗакрывающаяКруглаяСкобка)) то

Последнее особенно внезапно - количество скобок сократилось с 14 (или с 18, включая декоративные) до 4, выражение читается слева направо и сверху вниз (не нужно искать голову списка), не нужно парсить приоритеты операций, 4 (или 7-кратное) повторение слова "или" свернулось до 1-кратного. Здесь, конечно, крупно повезло, но это пример из жизни, а не синтетический, я не мухлевал. Я начинаю всерьёз думать о том, чтобы в Яре-23 сделать префиксную форму булевых операторов основной, а инфиксную - вспомогательной (с наценкой, что-нибудь типа ☼и, ☼или и т.п.)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Вторник, 11 Апрель, 2023 14:06 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Кстати, в Обероне вовсе не мало приоритетов в синтаксисе:
Код:

Выражение    =   ПростоеВыражение [Отношение ПростоеВыражение].
ПростоеВыражение    =   ["+" | "-"] Слагаемое {ОперацияСложения Слагаемое}.
Слагаемое    =   Множитель {ОперацияУмножения Множитель}.
Множитель    =   Обозначение [ФактическиеПараметры] | число | символ | строка | NIL | Множество | "(" Выражение ")" | "~" Множитель.
Множество    =   "{" [Элемент {"," Элемент}] "}".
Элемент    =   Выражение [".." Выражение].
ФактическиеПараметры     =   "(" [СписокВыражений] ")".
Отношение    =   "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
ОперацияСложения    =   "+" | "-" | OR.
ОперацияУмножения    =   "*" | "/" | DIV | MOD | "&"

Для сравнения, в С++ их 16, но таблички красвой не нашёл - две найденные слишком подробные и их ещё надо переформатировать, а лень. Но сравнивать надо 10 и 16, а не 16 и 4, как кто-то там утверждал в телеге. Во всяком случае, среди сишных операторов есть "оператор запятая" и "вызов функции". Если мы их выкидываем из сравнения, чтобы в Обероне стало 4 приоритета, то их и в случае C++ надо выкидывать из сравнения и там тоже может стать не 16 групп. Т.е. сравнение 4 и 16 носит ярко выраженный рекламный характер, а потом люди удивляются, что Оберон и оберонщиков закидывают тапками на Хабре. Пишите правду, тогда меньше будет поводов.

Если же сравнивать с лиспом, то там будет из операций только "разрешение области видимости", "макрос чтения", "символ", "список", "число", "цитата", "квазицитата", "подстановка в квазицитату". Казалось бы, 7 - это тоже много, но если мы выкинем квазицитаты, которые в Обероне в принципе отсутствуют как таковые, и будем сравнивать синтаксисы равной выразительной мощи, то получится уже 5. При том, макрос чтения тоже был бы под вопросом, если бы он не использовался в стандартном синтаксисе, например. #(1 2 3) - это вектор, но в то же время это макрос чтения. Это для тех, кто считает, что Оберон - это какой-то там сильно простой язык. Нифига он не простой, синтаксис у него довольно сложный. Синтаксис лиспа постижим (на нём написано уж точно не меньше полезных программ, чем на Обероне), а значит, если мы берём эпиграф "сделай просто как можно, но не проще", то в общем-то Вирт не пошёл до конца в оптимизации синтаксиса.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Вторник, 11 Апрель, 2023 19:01 

Зарегистрирован: Пятница, 11 Январь, 2019 19:26
Сообщения: 293
Откуда: Russia
if (x#y) or [a=b, z > f, e<s, h=I] then


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Вторник, 11 Апрель, 2023 20:33 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Это так можно в A2 через мат.массивы? А будет ли ленивость?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 12 Апрель, 2023 00:51 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1449
Откуда: Киев
budden писал(а):
Кстати, в Обероне вовсе не мало приоритетов в синтаксисе...
А свой способ подсчёта количества уровней приоритета операций не расскажете?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 12 Апрель, 2023 12:30 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Вам - не расскажу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 12 Апрель, 2023 16:06 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1449
Откуда: Киев
Потому что знаете, что он неправильный?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 12 Апрель, 2023 16:55 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
Нет, просто не расскажу, и всё :lol:


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сложные логические выражения
СообщениеДобавлено: Среда, 12 Апрель, 2023 17:19 

Зарегистрирован: Понедельник, 11 Сентябрь, 2017 13:23
Сообщения: 1565
В Хаскеле в выражениях порядка 10 приоритетов. Ситуация отягощается тем, что можно задавать свои операции с различными (чуть ли не любыми) приоритетами. Вот тут есть мнения на тему, где объясняется, что сильно меньше 10 будет тяжело добиться, и рассказывается о проблемах людей с этим: https://stackoverflow.com/questions/632 ... -10-enough


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 43 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 19


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB