- PVSM.RU - https://www.pvsm.ru -

Обратная сторона лаконичности знаков в языках программирования

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

Далее подробно рассмотрены факторы, влияющие на трудоёмкость осмысления знаков, а именно:

  • проговариваемый знак или разделительный;

  • относительное расположение знака;

  • нагруженность знака и его расположения;

  • таблица приоритетов операций, обозначаемых знаками;

  • очевидность и стандартность знака.

Эти факторы лежат в основе правил для отсеивания неудачных вариантов при выработке системы знаков в языках программирования. Правила сформулированы в конце. Они используются в том числе при разработке семейства языков Артель [1].

Цена лаконичности знаков

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

C#/Java      Oberon-07    Pascal       Артель
  =            :=           :=           =
  ==           =            =            ==
  !=           #            <>           !=
  &&           &            and          и
  ||           OR           or           или
  !            ~            not          не
  5/6          3/6          2/6          2/6

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

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

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

В речи человека есть слова, но нет знаков. Для проговаривания увиденного знака мозгу [2] приходится сначала искать соответствующее знаку слово. Если нет слова, то нет понимания. Поэтому даже матёрый профессионал вынужден осмысливать знаки &&, ||, ! через проговаривание их в уме в виде слов и, или, не. Новичку же для начала нужно натренировать свой мозг [2] на проговаривание знаков нужными словами.

а && б             а и б
а || б             а или б
!а                 не а

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

!а
а!

!(а || б)
ф!(а || б)

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

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

!(а.выкл||а.сбой&&а.резервирование)

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

!(а.выкл || а.сбой && а.резервирование)

не(а.выкл или а.сбой и а.резервирование)

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

если !вкл тогда ...
если не(вкл) тогда ...

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

PERASPERAADASTRA
PER·ASPERA·AD·ASTRA
PER ASPERA AD ASTRA

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

.   ,   ;   :   !   ?   !?   ...

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

а = б + в          а равно б плюс в

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

Число[]            [] проговаривается как «массив»
[]Число            [] проговаривается как «массив»

Массив<Число>      < и > являются разделительными

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

Привет!               правостороннее
#программирование     левостороннее
@пользователь         левостороннее
-а                    левостороннее
а - б                 внутреннее
человек-амфибия       внутреннее
(фрагмент текста)     пара: открывающее, закрывающее
"Текст в кавычках"    и открывающее и закрывающее
м[...]                правосторонне-открывающее

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

  • правостороннее, открывающее и закрывающее расположение наиболее распространённое, поэтому его осмысливать легче всего;

  • внутреннее расположение менее распространено, поэтому осмысливать его уже тяжелее;

  • левостороннее расположение наименее распространено, поэтому осмысливать его тяжелее всего;

Если знак располагается так, как это не принято в школьной литературе и математике, то это существенно увеличивает умственные усилия по осмыслению.

!вкл!
?название
?объект?.код
!объект!.код
[]Число
Число[]

Затруднение в таких случаях связано с тем, что мозг [2] вынужден убеждаться, что это не ошибка, а намеренная запись. Ведь несвойственная вещь нуждается в перепроверке. Для этого мозгу [2] приходится изучать окрестности вокруг знака.

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

Число 1.234,5 меньше числа 5.432,1.

если а + б = 0, то б = -а

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

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

а?
?а

Цена неочевидности приоритетов

Отдельного внимания заслуживают левостороннее и внутреннее расположение знака.

!а
а || б
а && б

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

!а!.б! || в == г

Точный смысл:

(!(а!.б!)) || (в == г)

Процесс осмысления:

(!а!.б! || в == г        отсекаем правостороннюю форму
(!(а!.б! || в == г       начинаем поиск правой границы
(!(а)!.б! || в == г
(!(а!).б! || в == г
(!(а!.)б! || в == г
(!(а!.б)! || в == г
(!(а!.б!) || в == г      упёрлись в меньший приоритет
...
(!(а!.б!)) || (в == г)   похоже это именно оно
...
(!(а!.б! || в == г)      не похоже на правду

Для сравнения:

не(а!.б!) или в == г

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

Постфиксные       ++   --
Унарные           ++   --   +    -    ~   !
Умножение         *    /    %
Сложение	        +    -
Сдвиги            <<   >>   >>>
Отношения         <    >    <=   >=   instanceof
Сравнения         ==   !=
Бинарное «и»      &
Бинарное «искл»   ^
Бинарное «или»    |
Логическое «и»    &&
Логическое «или»  ||
Тернарные         ? :
Присваивания      = += -= *= /= %= &= ^= |= <<= >>= >>>=

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

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

?а!.б! || в == г    "?" работает также как "!" или нет?

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

(?(а!.б!)) || (в == г)

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

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

Всё это свидетельствует о принципиальной важности количества знаков в языке и важности размера таблицы приоритетов. Таблица приоритетов это не просто справочник. Это та незримая работа, которую мозг [2] проделывает при виде каждого знака. И это стоит учитывать при выработке системы знаков в языке.

Польза стандартных знаков

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

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

Проговариваемые:

=      равно (теперь равно, изменить на)
+      плюс
-      минус
*      умножить на
/      поделить на
<      меньше
<=     меньше либо равно
>      больше
>=     больше либо равно
->     превращается в
=>     следовательно

Разделительные:

,      разделитель перечисляемых элементов
;      разделитель самостоятельных фраз
"      начало и конец обособленного текста
()     начало и конец подчинённого фрагмента

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

Проговариваемые:

==     равно
!=     не равно
+=     увеличить на
-=     уменьшить на
*=     приумножить (в N раз)
/=     сократить (в N раз)
%      взять остаток от деления на
!      не (отрицание, левостороннее расположение)

Разделительные:

.      уточнение имени
:      указание типа данных
[]     начало и конец списка ключей или элементов
{}     начало и конец блока
//     комментарий
      экранирование

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

?:   !!   ..<   &<<   &>>   &*   ~=   и др.

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

Зачем новичку тренировать свой мозг [2] на распознавание нестандартных знаков? Ведь затем при изучении популярных языков программирования придётся заново осваивать уже стандартные знаки.

Учимся:

а := б
если а = б & в # г тогда ...

Переучиваемся:

а = б
если а == б && в != г тогда ...

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

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

~a     логическое или битовое?
~"а"   маркер? или есть понятие отрицания текста?
?a     что бы это могло значить...

И самый матёрый полиглот, и закоренелый фанат, и крепкий середнячок превращается в растерянного новичка, когда видит в языке программирования знак, который раньше не видел или подзабыл со временем, или который до сего момента значил для него нечто другое. О
новичках, середнячках, фанатах и полиглотах подробнее в здесь [3].

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

Например, можно подумать над тем, чтобы отказаться от стандартных знаков << и >> для обозначения битовых сдвигов. Такие знаки осложняют использование одиночных знаков < и > в качестве угловых скобок, например, при обозначения параметров в шаблонах типов
Массив<Число>. Ведь при наличии угловых скобок знак >> перестаёт быть однозначной лексемой.

Массив<Массив<Число>>      >> или же > и ещё раз >

Это одна из причин, по которой знаки битовых операций отсутствуют в списке стандартных выше.

Правила отсеивания знаков

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

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

  • знак не подходит, если он в таком же качестве применяется менее, чем в {А}% самых популярных языков;

  • знак не уместен, если его расположение чуждо школьной литературе и математике;

  • знак не нужен, если программист видит обозначаемое им понятие в тексте программы
    реже одного раза в {Б} дней;

  • знак не целесообразен, если существует полное или сокращённое слово длиной до {В} букв включительно;

  • но знак может быть исключением из правил, если в языке программирования не более {Г} таких исключений.

Путём подстановки нужных значений А-Б-В-Г можно ограничить себя определёнными рамками.

Например, формула 70-365-3-1 фиксирует, что в языке допустимы лишь очевидные и стандартные знаки с таким же смыслом как минимум в 70% наиболее популярных языков,
нужные программисту не реже одного раза в 365 дней и не имеющие подходящего полного/сокращённого слова длиной до 3 букв включительно, но с правом на 1 исключение из всех этих правил.

Формулы 70-900-4-3 и 70-100-3-0 используются в языках семейства Артель [1].

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

Справочник

Полный список формальных характеристик знака:

Очевидный                       : да/нет
Стандартный                     : да/нет
Нестандартный                   : да/нет
Проговариваемый                 : да/нет
Разделительный                  : да/нет
Расположение правостороннее     : да/нет
Расположение внутреннее         : да/нет
Расположение левостороннее      : да/нет
Расположение открывающее        : да/нет
Расположение закрывающее        : да/нет
Вариативность расположения      : от 1 до 7
Чуждость расположения           : от 1 до 6
Нагрузка                        : целое число
Нагрузка расположения           : целое число

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

Дополнительные определения:

  • вариативность расположения – это количество возможных расположений знака без учёта смысловой нагрузки;

  • чуждость расположения – это количество возможных расположений знака, которые не встречаются в школьной литературе и математике;

  • нагрузка знака – это количество смыслов, которые может иметь знак в зависимости от расположения и контекста;

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

Автор: ychetyrko

Источник [4]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/446405

Ссылки в тексте:

[1] Артель: https://artel.by

[2] мозгу: http://www.braintools.ru

[3] здесь: https://blog.nezaboodka.com/post/2026/600-language-users

[4] Источник: https://habr.com/ru/articles/1008266/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1008266