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

Определение

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

Необходимо отметить, что понятие синтаксического сахара во многом условно. Его использование предполагает, что из всего множества синтаксических конструкций можно выделить некоторый «базовый набор», обеспечивающий всю функциональность языка, и тогда дополнительные синтаксические средства, которые при желании можно выразить с помощью базового набора, и будут для данного языка синтаксическим сахаром. Однако многие конструкции являются взаимозаменяемыми, и далеко не всегда можно определённо сказать, какие именно из них являются базовыми, а какие — дополнительными. Например, в языке Модула-2 есть четыре вида циклов: цикл с предусловием, цикл с постусловием, цикл с шагом и безусловный цикл. Теоретически, первые три вида циклов могут быть легко выражены через последний. Являются ли они, в таком случае, синтаксическим сахаром? Обычно так не говорят, хотя формально под вышеприведённое определение они попадают.

Примеры

Сокращённые операторы

В языке Си и его потомках (C++, Java, C# и другие), а также во многих других, имеется отдельный синтаксис для операций увеличения, уменьшения и упрощённого присваивания:

Увеличение и уменьшение 
унарные операторы ++ и -- обеспечивают, соответственно, увеличение и уменьшение значения переменной на единицу. Оба оператора имеют две формы — префиксную и постфиксную. В префиксной форме выражение имеет значение, соответствующее новому значению переменной, в постфиксной — старому.
int x = 10;
int y = 10;
 
a = x++; // постфиксная форма - эквивалентно a = x , x = x + 1;
b = --y; // префиксная форма - эквивалентно y = y - 1, b = y;
Сокращённое присваивание 
для выражений вида «<переменная> = <переменная> <знак операции> <значение>» введена сокращённая форма записи «<переменная> <знак операции>= <значение>»:
int x = 10;
int y = 10;
 
x += 10; // эквивалентно x = x + 10; 
y -= 5; // эквивалентно y = y - 5;
y *= x; // эквивалентно y = y * x;
x /= y; // эквивалентно x = x / y;

и т. д.

Сокращённые операторы были введены в Си из соображений эффективности — в машинном коде компьютера PDP-11, для которого и разрабатывался язык, существовали отдельные команды INC x и DEC x («увеличить на 1» и «уменьшить на 1», соответственно), более короткие и быстрые, чем ADD #1,x и SUB #1,x; компилятор языка Си превращал ++ и -- именно в эти команды. В настоящее время язык Си используется на огромном количестве различных вычислительных платформ, у которых такие «сокращённые» команды либо не дают ощутимого выигрыша, либо вовсе отсутствуют; с другой стороны, оптимизирующие компиляторы умеют выявлять возможности сокращения кода и генерируют абсолютно одинаковый код как для x++, так и для x = x + 1, так что сокращённые команды превратились в самый настоящий синтаксический сахар.

Массивы в Си

Массивы в Си представляют собой блоки в памяти. Доступ к элементам массива производится через указатель на начало блока памяти (то есть, на начало массива) и смещение элемента относительно начального адреса. Это может быть записано без использования специального синтаксиса для массивов (a — указатель на начало массива, i — индекс необходимого элемента): *(a + i), но непосредственные операции с адресами в памяти и смещениями являются большим источником ошибок программистов, поэтому язык предоставляет специальный синтаксис: a[i]. Кроме того, есть возможность обратиться к i-му элементу массива уж совсем экзотическим способом: i[a], что аналогично a[i], так как значение указателя i+a, очевидно, равно a+i.

Тернарная операция в Си

Другой известный пример специализированной языковой конструкции — тернарная условная операция языка Си ?:. Следующие два фрагмента кода делают одно и тоже:

int fn();
int a = 1;
int b;
if (a > 0)
    b = fn(1);
else
    b = fn(2);


int fn();
int a = 1;
int b = fn((a > 0)? 1 : 2);

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

Переопределение операторов

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

Свойства

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

Критика

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

Известен афоризм Алана Перлиса: «Синтаксический сахар вызывает рак точек с запятой». Точка с запятой («;»), являясь обязательной частью большинства популярных языков программирования, даже если в новом языке бесполезна, оставляется как необязательный элемент, так как большинство программистов имеют прочную привычку её использования. В оригинале афоризм обыгрывает созвучие английских слов semicolon (точка с запятой) и colon, последнее из которых означает не только двоеточие, но и прямую кишку (colon cancer — рак прямой кишки).

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

Синтаксическая соль

С «синтаксическим сахаром» тесно связано понятие «синтаксическая соль» (англ. syntactic salt)[1] — на жаргоне хакеров конструкция в языке программирования, которая требует от программиста подтверждения того, что он делает. В отличие от «синтаксического сахара», который расширяет свободу выражения программиста, «синтаксическая соль» её сужает, требуя «без причины» писать длинные конструкции.

В Jargon File написано: «синтаксическая соль вредна, поскольку повышает артериальное давление хакера». Однако «промышленным» программистам, которые перегружены работой, зачастую рутинной, и квалификацией не дотягивают до хакеров, «синтаксическая соль» помогает не ошибаться.

Примеры:

  • Директива override в Delphi: при изменении в базовом классе программист будет вынужден внести те же изменения в классы-потомки, иначе программа не будет компилироваться.
  • Операция reinterpret_cast в C++: как напоминание, что подобное преобразование типов небезопасно.

Примечания

  1. syntactic salt

Литература

  • Синтаксический сахар в The Jargon File


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

© 2021–2023 sud-mal.ru, Россия, Барнаул, ул. Денисова 68, +7 (3852) 74-95-52