Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Изменение приоритетов операций

Надо отдать должное Владиславу, он точно заметил слабое место в этой рационализации — приоритеты операций. Логические и побитовые операции имеют разный приоритет. Их объединение сделает приоритет выполнения одинаковым. Что может принести неудобства:

// Пример Владислава:
MaybeUTF8 := (FirstByte and $С0 = $80) and (NextByte and $С0 = $80);		// Паскаль-вариант

MaybeUTF8 = FirstByte & 0xC0 == 0x80 && NextByte & 0xC0 == 0x80;		// Си-вариант
MaybeUTF8 = ((FirstByte & 0xC0) == 0x80) && ((NextByte & 0xC0) == 0x80);	// эквивалент со скобками 

// В каком порядке будет вычисляться это выражение при одинаковых приоритерах «&» и «&&»?
Изменение приоритетов операций
            Однако это не меняет того факта, что логические операции и побитовые операции применяются к разными типами данных. Поэтому логично заставить одни и те же операции решать разные задачи — в зависимости от типа данных. Проблему приоритетов логично решить неожиданным способом. Можно иметь две одинаковые по семантике операции «и», но с разными приоритетами:
результат = флаг 1 & флаг 2 && флаг 3

Повышение приоритета операций дублированием символа операции

            Операция «и», записанная двумя символами «&&», более приоритетна, нежели «&» — c одним символом. При одинаковом их смысле. Очерёдность выполнения операций будет такова:
1) флаг 2 && флаг 3			// в первую очередь
2) флаг 1 & результат 1-го шага	// во вторую очередь
3) результат = результат 2-го шага	// в третью очередь
Аналогично — для операций «или» и «исключающее или»:
результат = флаг 1 | флаг 2 || флаг 3
результат = флаг 1 ^ флаг 2 ^^ флаг 3
Если знаки операций записываются словами, то и тут можно попробовать одинаковым операциям назначить разный приоритет:
результат = флаг 1 and флаг 2 AND флаг 3	// больше буквы — больше приоритет
результат = флаг 1 or флаг 2 OR флаг 3
результат = флаг 1 xor флаг 2 XOR флаг 3
            Внимательный читатель заметит, что в приведённых выше примерах результат не зависит от порядка вычислений. Но примеры тут даны такие, чтобы иллюстрировать саму идею.

            Поскольку в будущем языке программирования важно придерживаться единого стиля — так легче постигается язык, то закономерно встанет вопрос о «симметричных» операциях. Об операциях «++», «--», «**» и «//», как более приоритетных вариантах всё тех же операций «+», «-», «*» и «/». Почему бы нет? Непривычно будет поначалу, конечно. Но ведь можно будет сэкономить на скобках.

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

Повышение приоритета операций многократным повторением символа операции

            Там, где можно поставить два символа подряд, можно поставить и три, и четыре — сколько надо:
a = b ** c ++++ d /// e	        // первым выполнится сложение
				// вторым — деление
				// третьим — умножение
				// четвёртым — присвоение
f = b * ((c + d) / e)		// эквивалентная запись в традиционной форме
            В таком случае вообще отпадает надобность в традиционных скобках. Можно ли вообще без них обойтись? Сложности возникают вот где. В C/C++ много операций, записанных двумя и тремя символами, а то и буквами. Например:
->	// доступ к члену класса по указателю на объект
new	// создание динамического объекта
->*	// обращение к члену класса по указателю на него
<=	// логическая операция: меньше или равно
>>=	// присваивание со сдвигом вправо
И как должна быглядеть Какие идеи? И чтоб попроще!

Повышение приоритета операций специальным символом

            Для приоритета операций можно выбрать какой-то специальный символ. Какой именно, надо подумать. Но пока что для обсуждения выберем «^» — треугольник вершиной вверх, которого нет на клавиатуре.
a ^= b ▲▲▲% c ▲▲!= 0 ▲| d ▲▲▲<< 2 ▲▲== e
a ^= ((b % c) != 0) | ((d << 2) == e)		// эквивалентная запись в традиционной форме
Какая запись нагляднее — обсуждаемая или традиционная?

Понижение приоритета операций специальным символом

            Приоритеты операций можно не только повышать, но и понижать:
a ▼▼^= b ▲% c != 0 ▼| d ▲<< 2 == e
Такой вариант тоже имеет право на рассмотрение.

Переопределение операций

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

Плюсы и минусы

            Плюсы:
  • делает возможным запись выражений без скобок. Скобки, честно говоря, не слишком хороший ориентир при визуальном анализе выражений.
  • программист может писать выражения, будучи уверенным, что порядок операций будет таким, как он задумал, без заглядывания в таблицу приоритетов. То есть упор на логику, а не на память.
            Минусы:
  • Ломает традиции. Наверно, даже чересчур.
  • Операции «++» (инкремент), «--» (декремент), «**» (возведение в степень) оказываются «заняты», а комментарии и вовсе придётся записывать по-другому из-за «//». А каким символам с клавиатуры должны соответствовать «▲» и «▼» — вообще непонятно.

Вычисление приоритетов в выражениях

            Формула расчёта приоритета операции:
<итоговый приоритет> = <множитель> * <число приоритетов> + <собственный приоритет>
где:
  • <множитель> — количество повышений приоритета (количество символов «▲» или уровень вложенности скобок).
  • <число приоритетов> — количество возможных приоритетов в языке программирования. В C++ число приоритетов, в зависимости от источника информации, колеблется 14 до 17.
  • <собственный приоритет> — приоритет конкретной операции. Например, в C++ приоритет операции «=» равен 1 (если отсчёт с нуля), а операции «||» равен 2. Отсчёт от нуля, чем выше приоритет — тем раньше выполнится операция. самый низкий приоритет — нулевой.

Нужен ли ещё один синтаксический сахар?

Когда-то был популярен такой упрёк в адрес Microsoft:

Вместо того, чтобы повысить надёжность программ, убрать все ошибки, сделать интерфейс проще и удобнее и убрать тормоза, они добавляют лишние свистки и колокольчики! Кому нужна лишняя функциональность? Лучше бы побороли глюки!

            И с этой идеей можно предъявить претензии в том же духе: «Сколько можно совершенствовать синтаксис? Зачем нужна ещё одна форма записи? Может, лучше поработать не над формой, а над содержанием?» И в этих словах будет немало истины...

P.S. «Ну, за проезд!» Когда-то Владислав напомнил мне анекдот:

В автобусе едет мужик. Достал бутылку водки и стакан, налил себе, поднёс ко рту и застыл в ступоре, вроде как забыл что-то важное. А тут по автобусу идёт контролёр:
— Мужчина, за проезд!
Тут его осенило:
— Ну, за проезд!

И вот пару лет спустя Владислав стал тем самым автобусным контролёром, который подтолкнул мою фантазию к теме приоритетов операций :)

Опубликовано: 2018.11.23, последняя правка: 2018.11.27    22:32

ОценитеОценки посетителей
   ██████████████ 1 (33.3%)
   ▌ 0
   ██████████████ 1 (33.3%)
   ██████████████ 1 (33.3%)

Отзывы

     2018/11/26 11:57, ВежливыйЛис          # 

Диез и бемоль — для повышения и понижения

     2018/11/26 12:33, Автор сайта          # 

Есть такие символы в Юникоде: ♯, ♭. Но их нет на клавиатуре. Не лучший для языка вариант — использовать то, чего нет на клавиатуре. Ну и большинство не знакомо с нотной грамотой. Зачем использовать неочевидные для этих людей символы?

     2018/11/27 02:25, ВежливыйЛис          # 

Кроме изменения приоритета, можно ещё дополнять состав операций.

В спецификации языка опубликовать API к генератору кода, придумать синтаксис для описания операции (например некую смесь из EBNF и обращений к API).

Гейт переводит одно состояние регистра в другое. Действие гейта на регистр можно записать так: G∣R⟩=∣R′⟩

     2018/11/27 14:45, Comdiv          # 

Всё это только запутывает.

     2018/11/27 22:26, Автор сайта          # 

ВежливыйЛис: Далёк я от квантовых гейтов и этой темы вообще... Если Вы имеете в виду прямо в языке описывать использование регистров процессора, то это слишком низкий уровень. Управление «железом» надо прятать под капот.
Comdiv: Мне кажется, что если выбирать из описанных выше вариантов, то наиболее доходчивый из них — повышение приоритета повторением символа. Типа «+++». Но это не повод отменять скобки. А Ваш выбор какой? Не трогать традиции, ничего не выдумывать, оставить всё как есть?

     2018/11/28 14:35, Comdiv          # 

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

     2018/11/28 22:25, Автор сайта          # 

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

     2018/11/29 04:50, Freeman          # 

Дополнение состава операций есть в языке Эйфель (Eiffel) Бертрана Мейера. В нем есть даже «функциональные клавиши» — комбинации значков, не назначенные никакой операции, — с расчетом на то, чтобы программистам было куда привязывать свои придумки, не перекрывая традиционные.

Повышение приоритета повторением превращает язык операций в вики-разметку: 2+++1 без пробелов больше невозможны, нужно явно писать 2++ + 1, 2 + ++1 или 2 +++ 1.

С точки зрения вики-разметки клавиши ▲ и ▼ на клавиатуре есть. Это скобки. Дело в том, что указание приоритетов в самом выражении (а не в DSL/настройках) вынуждает читателя кода работать стековой машиной. Человеческий мозг — плохая стековая машина. Для повышения человечности нужно переходить от стека к визуальному представлению, что и возвращает нас к скобкам.

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

     2018/11/29 16:11, Автор сайта          # 

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

Согласен. Она, по крайней мере, прошла проверку временем.

2+++1 без пробелов больше невозможны

Возможны, если пожертвовать инкрементом, т.е. за инкрементом закрепить другие символы, а «+» оставить только за сложением.

     2018/11/30 17:56, Freeman          # 

Перевод инкремента на другие символы — снова нарушение правила вики.

     2019/01/10 07:40, utkin          # 

Очень мутное объяснение которое будет только запутывать. Я из статьи, например, не понял — зачем создавать конкуренцию всем известным скобкам? Все эти поднятия и опущения только усложняют восприятие. Имеется готовое стандартное, решение которое отлично состыковано с другими сферами деятельности. Это скобки. Зачем все это усложнять? Автор статьи так и не объяснил.

     2019/01/10 07:46, utkin          # 

результат = флаг 1 & флаг 2 && флаг 3

Сиди потом и ищи ошибку — где ты пропустил & или где там один лишний? Вы и я будем придерживаться простых решений, а кто-то нарисует что-то типа:
результат = флаг 1 & флаг 2 && флаг 3 && флаг 3 & флаг 2 && флаг 1 & флаг 3
Вот Вам и вырвиглаз. У программиста и так куча возможностей всё испортить, зачем давать ещё одну? Просто впишите скобки и все понятно, просто потому, что человек их использует чуть более, чем везде и такой аппарат он получает из других дисциплин, типа школьного курса математики. Просто сравниваем два инструмента и? Плюсы? Не вижу. Минусы? ещё один способ все намудрить, усложнить и запутать.

Любой инструмент должен иметь целевую функцию — полезность. Если о ней речь не ведется в принципе, то такой инструмент НЕ НУЖЕН.

     2019/01/11 07:22, utkin          # 

a = b ** c ++++ d /// e	
А что если человек пропустил в конце тяжелого рабочего дня какой-то коэффициент?
Например:
a = b ** c +++ f + d /// e	
Все-таки сделать такой финт со скобками сложней, потому что их нужно две и пропуск одного коэффициента моментом подтвердится как ошибка, также как и пропущенная скобка. А может у меня клавиатура в крошках и один плюс не прожался?
a = b ** c +++ d /// e
Когда этих плюсов там много они будут сливаться и считать их в сложном выражении это та ещё будет радость. Вы не просто даете возможность выстрелить в ногу. Вы даете пулемет с бесконечным числом патронов.

     2021/03/27 23:46, Виталий Монастырский          # 

Опять голая проблема на пустом месте.

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

Разграничение одного от другого наилучшим образом решается просто — логические операторы пишутся словами: and, or, xor, not, а побитовые операции знаками — &, |, ^, ~. Все, это позволяет наилучшим образом их разграничить и улучшить читаемость сложных выражений.

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

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

Нет в этом никакой проблемы. Просто нет. И рожать её на пустом месте... ну, лучше на что-либо более осмысленное время потратить.

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

●  Устарел ли текст как форма представления программы

●  Русский язык и программирование

●  Многоязыковое программирование

Синтаксис языков программирования

Синтаксический сахар

●  Некоторые «вкусности» Алгол-68

●  «Двухмерный» синтаксис Python

●  Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

●  Должна ли программа быть удобочитаемой?

●  Стиль языка программирования

●  Тексто-графическое представление программы

●●  Разделители

●●  Строки программы

●●  Слева направо или справа налево?

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

●●  Длинные комментарии

●●  Короткие комментарии

●●  Комментарии автоматической генерации документации

●●  Нерабочий код

●●  Помеченные комментарии

●  Нужны ли беззнаковые целые?

●  Шестнадцатиричные и двоичные константы

●  Условные операторы

●  Переключатель

●  Циклы

●●  Продолжение цикла и выход из него

●  Некошерный «goto»

●  Изменение приоритетов операций

●  Операции присвоения и проверки на равенство. Возможно ли одинаковое обозначение?

●  Так ли нужны операции «&&», «||» и «^^»?

●  Постфиксные инкремент и декремент

●  Почему в PHP для конкатенации строк используется «.»?

●  Указатели и ссылки в C++

●●  О неправомерном доступе к памяти через указатели

●  Обработка ошибок

●  Функциональное программирование

●●  Нечистые действия в чистых функциях

●●  О чистоте и нечистоте функций и языков

●●  Макросы — это чистые функции, исполняемые во время компиляции

●●  Хаскелл, детище британских учёных

●●  Измеряем замедление при вызове функций высших порядков

●●  C vs Haskell: сравнение скорости на простом примере

●●  Уникальность имён функций: за и против

●●  Каррирование: для чего и как

●●  О тестах, доказывающих отсутствие ошибок

●  Надёжные программы из ненадёжных компонентов

●●  О многократном резервировании функций

●  Использование памяти

●  Почему динамическое распределение памяти — это плохо

●  Как обеспечить возврат функциями объектов переменной длины?

●●  Типы переменного размера (dynamically sized types, DST) в языке Rust

●●  Массивы переменной длины в C/C++

●●  Размещение объектов в стеке, традиционный подход

●●  Размещение объектов переменной длины с использованием множества стеков

●●  Размещение объектов переменной длины с использованием двух стеков

●●  Реализация двухстековой модели размещения данных

●●  Двухстековая модель: тесты на скорость

●●  Изменение длины объекта в стеке во время исполнения

●●  Размещение объектов переменной длины с использованием одного стека

●  Можно ли забыть о «куче», если объекты переменной длины хранить в стеке

●  Безопасность и размещение объектов переменной длины в стеке

●  Массивы, структуры, типы, классы переменной длины

●  О хранении данных в стеке, вместо заключения

●  Реализация параметрического полиморфизма

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/04/18 11:14 ••• Ivan
Энтузиасты-разработчики компиляторов и их проекты

2024/04/18 04:47 ••• void
Признаки устаревшего языка

2024/04/11 00:08 ••• Автор сайта
Постфиксные инкремент и декремент

2024/04/09 23:50 ••• Автор сайта
Русский язык и программирование

2024/04/07 15:33 ••• MihalNik
Все языки эквивалентны. Но некоторые из них эквивалентнее других

2024/04/01 23:39 ••• Бурановский дедушка
Новости и прочее

2024/04/01 23:32 ••• Бурановский дедушка
Русской операционной системой должна стать ReactOS

2024/03/22 20:41 ••• void
Раскрутка компилятора

2024/03/20 19:54 ••• kt
О многократном резервировании функций

2024/03/20 13:13 ••• Неслучайный читатель
Надёжные программы из ненадёжных компонентов

2024/03/07 14:16 ••• Неслучайный читатель
«Двухмерный» синтаксис Python

2024/03/03 16:49 ••• Автор сайта
О неправомерном доступе к памяти через указатели

2024/02/28 18:59 ••• Вежливый Лис
Про лебедей, раков и щук