
Обратная сторона лаконичности знаков в языках программирования
Считается, что знаки повышают выразительность языка программирования, поскольку делают текст программы более лаконичным. С этим трудно не согласиться, но есть и обратная сторона. По сравнению с обычными словами знаки требуют дополнительных умственных усилий при их осмыслении человеком.
Далее подробно рассмотрены факторы, влияющие на трудоёмкость осмысления знаков, а именно:
- проговариваемый знак или разделительный;
- относительное расположение знака;
- нагруженность знака и его расположения;
- таблица приоритетов операций, обозначаемых знаками;
- очевидность и стандартность знака.
Эти факторы лежат в основе правил для отсеивания неудачных вариантов при выработке системы знаков в языках программирования. Правила сформулированы в конце. Они используются в том числе при разработке семейства языков Артель.
Цена лаконичности знаков
Начать размышления имеет смысл с базовых операций и их обозначений в нескольких языках программирования.
C#/Java Oberon-07 Pascal Артель = := := =
== = = ==
!= # <> !=
&& & and и
|| OR or или
! ~ not не 5/6 3/6 2/6 2/6По этой таблице можно заметить, что первый столбец воспринимается сложнее по сравнению с остальными. Сложность коррелирует с дробями, указанными внизу таблицы. Это удельное число знаков, которые не присущи школьной литературе и математике (либо имеют там совершенно иной смысл).
Чтобы понять трудоёмкость осмысления знаков, стоит кратко коснуться самого процесса осмысления текста человеком. Этот процесс представляет собой внутренний монолог – человек мысленно проговаривает слова для построения смыслов в собственном воображении.
Необходимость мысленно проговаривать слова текста, вероятно, связана с тем, что речь предшествует письменности. Человек сначала учится распознавать окружающую речь и говорить, и лишь затем писать и читать. Соответственно читаемые слова и знаки человек осмысливает через более базовый аппарат – речевой.
В речи человека есть слова, но нет знаков. Для
проговаривания увиденного знака мозгу приходится
сначала искать соответствующее знаку слово. Если нет
слова, то нет понимания. Поэтому даже матёрый
профессионал вынужден осмысливать знаки &&, ||, !
через проговаривание их в уме в виде слов и, или,
не. Новичку же для начала нужно натренировать свой
мозг на проговаривание знаков нужными словами.
а && б а и б
а || б а или б
!а не аПопутно новичку приходится ломать все свои представления о том, где обычно пишут восклицательный знак. Ведь и в литературе, и в математике восклицательный знак принято записывать после чего-то, а не до. Однако не забывать при этом, что всё-таки восклицательный знак может быть записан и после чего-то, придавая уже совсем другой смысл.
!а
а!
!(а || б)
ф!(а || б)И тут возникает закономерная мысль. А стоит ли эта
ломка того, чтобы сокращать слово из двух букв не до
одного знака !?.. И зачем нагружать мозг лишней
работой по превращению знаков в слова «и», «или», «не»,
если сами слова и так предельно короткие?.. Ведь жизнь
уже поработала над их лаконичностью.
Можно, конечно, рассуждать о том, что по сравнению со словами, знаки позволяют также экономить на пробелах. Но осмысливать длинные непрерывные последовательности букв и знаков человеку крайне тяжело.
!(а.выкл||а.сбой&&а.резервирование)Поэтому на практике пробелы всё же оставляют. И тогда оказывается, что разница в лаконичности между знаками и словами в логических выражениях практически отсутствует.
!(а.выкл || а.сбой && а.резервирование)
не(а.выкл или а.сбой и а.резервирование)По сути, более лаконичным по сравнению со словами можно назвать лишь тривиальный случай записи с восклицательным знаком, когда отрицаемое им не содержит пробелов. Но зачем дополнительная лаконичность в тривиальных случаях?
если !вкл тогда ...
если не(вкл) тогда ...Выше затронут фактор пробелов. Они сильнейшим образом влияют на восприятие текста человеком. В античности все слова записывали слитно без пробелов. Читать было тяжело, поэтому слова начали разделять средними точками, а позднее просто пробелами.
PERASPERAADASTRA
PER·ASPERA·AD·ASTRA
PER ASPERA AD ASTRAС развитием естественных языков начали появляться и другие разделительные знаки, например, знаки пунктуации. Они использовались для управления интонацией при чтении вслух: паузы, восклицания, вопросы и т.д. При чтении про себя эти знаки помогают легче распознавать структуру текста и акценты. Такие знаки не требуют обязательного проговаривания в виде слов при чтении.
. , ; : ! ? !? ...А проговариваемые знаки появились позднее разделительных как средство повышения лаконичности и выразительности в науках, например, в арифметике.
а = б + в а равно б плюс вПроговариваемые знаки требуют больше умственных усилий для осмысления, чем разделительные. Это стоит учитывать при выборе знаков для языка программирования.
Число[] [] проговаривается как «массив»
[]Число [] проговаривается как «массив»
Массив<Число> < и > являются разделительнымиНа умственные усилия влияет также расположение знака относительно того, к чему он применяется. Расположение бывает правостороннее, левостороннее, внутреннее, открывающее и закрывающее. Все эти разновидности расположений применяются и в школьной литературе, и в математике, и в программировании.
Привет! правостороннее
#программирование левостороннее
@пользователь левостороннее
-а левостороннее
а - б внутреннее
человек-амфибия внутреннее
(фрагмент текста) пара: открывающее, закрывающее
"Текст в кавычках" и открывающее и закрывающее
м[...] правосторонне-открывающееОпираясь на опыт чтения самых разнообразных текстов со всевозможными комбинациями расположения знаков, можно заметить следующее:
- правостороннее, открывающее и закрывающее расположение наиболее распространённое, поэтому его осмысливать легче всего;
- внутреннее расположение менее распространено, поэтому осмысливать его уже тяжелее;
- левостороннее расположение наименее распространено, поэтому осмысливать его тяжелее всего;
Если знак располагается так, как это не принято в школьной литературе и математике, то это существенно увеличивает умственные усилия по осмыслению.
!вкл!
?название
?объект?.код
!объект!.код
[]Число
Число[]Затруднение в таких случаях связано с тем, что мозг вынужден убеждаться, что это не ошибка, а намеренная запись. Ведь несвойственная вещь нуждается в перепроверке. Для этого мозгу приходится изучать окрестности вокруг знака.
Один и тот же знак может предполагать сразу несколько расположений. И каждое расположение может иметь несколько разных смыслов в зависимости от контекста. Поэтому один и тот же знак может быть нагружен многими смыслами, порой вообще не связанными между собой.
Число 1.234,5 меньше числа 5.432,1.
если а + б = 0, то б = -аВ примере выше знак точки в самом конце расположен справа и означает окончание предложения, а в числах он расположен внутри и означает разделение частей числа. А знак равно расположен между переменными и нагружен как вопросительным (сравнительным), так и утвердительным смыслом.
Нагруженность знака многочисленными расположениями и смыслами существенно увеличивает трудоёмкость осмысления. По этой причине следует с осторожностью относится к идее вводить левостороннее расположение знака в дополнение к правостороннему, когда знаков перестаёт хватать.
а?
?аЦена неочевидности приоритетов
Отдельного внимания заслуживают левостороннее и внутреннее расположение знака.
!а
а || б
а && бИх осмысление требует кроме всего прочего ещё и поиска границ того, на что знак воздействует. В языках программирования в таких ситуациях в дело вступает таблица приоритетов операций, которые этими знаками обозначаются. Именно эта таблица определяет границу того, на что знак воздействует.
!а!.б! || в == гТочный смысл:
(!(а!.б!)) || (в == г)Процесс осмысления:
(!а!.б! || в == г отсекаем правостороннюю форму
(!(а!.б! || в == г начинаем поиск правой границы
(!(а)!.б! || в == г
(!(а!).б! || в == г
(!(а!.)б! || в == г
(!(а!.б)! || в == г
(!(а!.б!) || в == г упёрлись в меньший приоритет
...
(!(а!.б!)) || (в == г) похоже это именно оно
...
(!(а!.б! || в == г) не похоже на правдуДля сравнения:
не(а!.б!) или в == гСитуация усугубляется тем, что из-за обилия знаков и слов в современных языках программирования их таблицы приоритетов такие огромные, что их никто не знает и даже не пытается запоминать. Для примера, одна из самых простых таблиц приоритетов среди современных промышленных языков:
Постфиксные ++ --
Унарные ++ -- + - ~ !
Умножение * / %
Сложение + -
Сдвиги << >> >>>
Отношения < > <= >= instanceof
Сравнения == !=
Бинарное «и» &
Бинарное «искл» ^
Бинарное «или» |
Логическое «и» &&
Логическое «или» ||
Тернарные ? :
Присваивания = += -= *= /= %= &= ^= |= <<= >>= >>>=Со временем, натренировав свой мозг на распознавание определённых знаков в рамках какого-то языка с какой-то таблицей приоритетов, профессиональный программист перестаёт чувствовать всю их сложность. Вроде бы как и нет проблемы.
Но это только до тех пор, пока профессионал не столкнётся в каком-то другом языке с новыми знаками, их новым качеством или другой таблицей приоритетов. Например, с левосторонним расположением знака вопроса, который в таком виде встречается крайне редко.
?а!.б! || в == г "?" работает также как "!" или нет?Если профессионалу приходится иметь дело одновременно с тремя и более языками программирования, то постоянно переключать в голове знаки и таблицы приоритетов становится проблематично. И чтобы избавиться от сомнений, ему становится проще явно обозначать границы и приоритеты с помощью круглых скобок и пробелов. Чтобы действовать наверняка и без всяких сюрпризов.
(?(а!.б!)) || (в == г)Таким образом, сложность осмысления левостороннего и внутреннего расположения знака напрямую зависит от сложности таблицы приоритетов операций. И каждый такой случай, тем более незнакомый и непривычный, является испытанием и для новичков, и для профессионалов. А поскольку зачастую такой знак нагружен многими смыслами, то сложность начинает зашкаливать.
А вот правостороннее расположение считывается легко, поскольку порядок применения знака просто соответствует порядку его записи в тексте.
Всё это свидетельствует о принципиальной важности количества знаков в языке и важности размера таблицы приоритетов. Таблица приоритетов это не просто справочник. Это та незримая работа, которую мозг проделывает при виде каждого знака. И это стоит учитывать при выработке системы знаков в языке.
Польза стандартных знаков
Трудоёмкость осмысления знака зависит также от его стандартности. Это единое понимание знака в рамках того или иного сообщества людей. Можно условно выделить очевидные, стандартные профессиональные и нестандартные знаки.
Очевидные знаки человек осваивает через школьную литературу и математику. И они постоянно на виду в повседневной жизни. Поэтому они наиболее понятны самому широкому кругу людей. Вот список очевидных знаков, которые в программировании удобно использовать со смыслом, близким к литературному или математическому:
Проговариваемые:
= равно (теперь равно, изменить на)
+ плюс
- минус
* умножить на
/ поделить на
< меньше
<= меньше либо равно
> больше
>= больше либо равно
-> превращается в
=> следовательно
Разделительные:
, разделитель перечисляемых элементов
; разделитель самостоятельных фраз
" начало и конец обособленного текста
() начало и конец подчинённого фрагментаСтандартные профессиональные знаки не являются очевидными для обычного человека, но широко используются в программировании и имеют одинаковое расположение и смысл в подавляющем большинстве наиболее популярных языков программирования (с заданной областью применения и целевой аудиторией).
Проговариваемые:
== равно
!= не равно
+= увеличить на
-= уменьшить на
*= приумножить (в N раз)
/= сократить (в N раз)
% взять остаток от деления на
! не (отрицание, левостороннее расположение)
Разделительные:
. уточнение имени
: указание типа данных
[] начало и конец списка ключей или элементов
{} начало и конец блока
// комментарий
\ экранированиеНестандартные знаки используются в своём конкретном смысле лишь в ограниченном количестве языков программирования. Поэтому они понятны в основном тем, кто постоянно имеет с ними дело по роду своей деятельности.
?: !! ..< &<< &>> &* ~= и др.С очевидными знаками сталкиваются все образованные люди по мере изучения школьной литературы и математики. Но изучение остальных знаков, будь они стандартные профессиональные или нестандартные, должно иметь некоторую целесообразность.
Зачем новичку тренировать свой мозг на распознавание нестандартных знаков? Ведь затем при изучении популярных языков программирования придётся заново осваивать уже стандартные знаки.
Учимся:
а := б
если а = б & в # г тогда ...
Переучиваемся:
а = б
если а == б && в != г тогда ...От детей постоянно звучит веский аргумент, что изучаемый ими в школе язык программирования «не настоящий и не пригодится в жизни». Честно говоря, на это сложно что-то возразить, даже если вы, как и автор этой статьи, душой тяготеете к какому-нибудь «ненастоящему» языку и считаете первый вид записи в примере выше более элегантным. Но с реальностью тоже приходится считаться.
Парадоксальным образом стандартность знака может быть более важна для профессионала, чем для новичка. Ведь если профессионал вынужден иметь дело одновременно с несколькими языками, то при частом переключении между ними легко запутаться и в знаках, и в смыслах. Знак становится не просто нагружен, а перегружен всевозможными смыслами.
~a логическое или битовое?
~"а" маркер? или есть понятие отрицания текста?
?a что бы это могло значить...И самый матёрый полиглот, и закоренелый фанат, и крепкий середнячок превращается в растерянного новичка, когда видит в языке программирования знак, который раньше не видел или подзабыл со временем, или который до сего момента значил для него нечто другое. О новичках, середнячках, фанатах и полиглотах подробнее в отдельной статье.
Тут важно заметить, что когда-то все знаки были нестандартными, включая арифметические. И стандартными они стали лишь со временем. А однажды могут и перестать ими быть, если практика выявит в них изъяны. Поэтому порой не нужно стесняться подвергать сомнению даже самые стандартные знаки.
Например, можно подумать над тем, чтобы отказаться от
стандартных знаков << и >> для обозначения битовых
сдвигов. Такие знаки осложняют использование одиночных
знаков < и > в качестве угловых скобок, например,
при обозначения параметров в шаблонах типов
Массив<Число>. Ведь при наличии угловых скобок знак
>> перестаёт быть однозначной лексемой.
Массив<Массив<Число>> >> или же > и ещё раз >Это одна из причин, по которой знаки битовых операций отсутствуют в списке стандартных выше.
Правила отсеивания знаков
Создание языка программирования и выработка его системы знаков – процесс творческий. А продуктивный творческий процесс нуждается хотя бы в минимальных правилах.
С учётом всего вышесказанного о трудоёмкости осмысления знаков, правила отсеивания неудачных вариантов могут выглядеть так:
- знак не подходит, если он в таком же качестве применяется менее, чем в {А}% самых популярных языков;
- знак не уместен, если его расположение чуждо школьной литературе и математике;
- знак не нужен, если программист видит обозначаемое им понятие в тексте программы реже одного раза в {Б} дней;
- знак не целесообразен, если существует полное или сокращённое слово длиной до {В} букв включительно;
- но знак может быть исключением из правил, если в языке программирования не более {Г} таких исключений.
Путём подстановки нужных значений А-Б-В-Г можно ограничить себя определёнными рамками.
Например, формула 70-365-3-1 фиксирует, что в языке допустимы лишь очевидные и стандартные знаки с таким же смыслом как минимум в 70% наиболее популярных языков, нужные программисту не реже одного раза в 365 дней и не имеющие подходящего полного/сокращённого слова длиной до 3 букв включительно, но с правом на 1 исключение из всех этих правил.
Формулы 70-900-4-3 и 70-100-3-0 используются в языках семейства Артель.
Сами формулы можно использовать не только как ограничительные рамки при выработке системы знаков, но и как способ оценки уже существующих систем знаков.
Справочник
Полный список формальных характеристик знака:
Очевидный : да/нет
Стандартный : да/нет
Нестандартный : да/нет
Проговариваемый : да/нет
Разделительный : да/нет
Расположение правостороннее : да/нет
Расположение внутреннее : да/нет
Расположение левостороннее : да/нет
Расположение открывающее : да/нет
Расположение закрывающее : да/нет
Вариативность расположения : от 1 до 7
Чуждость расположения : от 1 до 6
Нагрузка : целое число
Нагрузка расположения : целое числоВ расчётах и анализе каждое расположение знака с каждым конкретным смыслом для заданного контекста рассматривается как отдельный знак.
Дополнительные определения:
- вариативность расположения – это количество возможных расположений знака без учёта смысловой нагрузки;
- чуждость расположения – это количество возможных расположений знака, которые не встречаются в школьной литературе и математике;
- нагрузка знака – это количество смыслов, которые может иметь знак в зависимости от расположения и контекста;
- нагрузка расположения – это количество смыслов, которые может иметь одно конкретное расположение знака в зависимости от контекста.


