Введение
Синтаксис языка программирования, разработанный для удобства использования. В информатике синтаксический сахар — это синтаксис в языке программирования, предназначенный для облегчения чтения или выражения. Он делает язык "слаще" для человека: вещи можно выразить более ясно, лаконично или в альтернативном стиле, который может быть предпочтительнее. Синтаксический сахар обычно является сокращением для часто используемой операции, которую также можно выразить в альтернативной, более многословной форме. Программист может выбрать, использовать более короткую или более длинную форму, но обычно выбирает более короткую, так как она короче и легче для набора и чтения. Например, многие языки программирования предоставляют специальный синтаксис для обращения к элементам массива и их изменения. В абстрактном представлении обращение к элементу массива — это процедура с двумя аргументами: массив и вектор индексов, которую можно выразить как `get array(Array, vector(i,j))`. Вместо этого многие языки предоставляют синтаксис, такой как `Array[i,j]`. Аналогично, изменение элемента массива — это процедура с тремя аргументами, например, `set array(Array, vector(i,j), value)`, но многие языки также предоставляют синтаксис, такой как `Array[i,j] = value`. Конструкция в языке считается синтаксическим сахаром, если её можно удалить из языка без изменения его функциональности и выразительной силы. Языковые процессоры, включая компиляторы и статические анализаторы, часто преобразуют конструкции с синтаксическим сахаром в их более многословные эквиваленты перед обработкой, процесс, иногда называемый "десахаризацией".
In computer science, syntactic sugar is syntax within a programming language that is designed to make things easier to read or to express. It makes the language "sweeter" for human use: things can be expressed more clearly, more concisely, or in an alternative style that some may prefer. Syntactic sugar is usually a shorthand for a common operation that could also be expressed in an alternate, more verbose, form: The programmer has a choice of whether to use the shorter form or the longer form, but will usually use the shorter form since it is shorter and easier to type and read. For example, many programming languages provide special syntax for referencing and updating array elements. Abstractly, an array reference is a procedure of two arguments: an array and a subscript vector, which could be expressed as get array(Array, vector(i,j)). Instead, many languages provide syntax such as Array[i,j]. Similarly an array element update is a procedure consisting of three arguments, for example set array(Array, vector(i,j), value), but many languages also provide syntax such as Array[i,j] = value. A construct in a language is syntactic sugar if it can be removed from the language without any effect on what the language can do: functionality and expressive power will remain the same. Language processors, including compilers and static analyzers, often expand sugared constructs into their more verbose equivalents before processing, a process sometimes called "desugaring".
Происхождение
Термин «синтаксический сахар» был введен Питером Дж. Лэндином в 1964 году для описания поверхностного синтаксиса простого языка программирования, подобного ALGOL, который был семантически определен в терминах аппликативных выражений лямбда-исчисления, с акцентом на лексической замене λ на "where". Впоследствии языки программирования, такие как CLU, ML и Scheme, расширили это понятие, чтобы оно относилось к синтаксису внутри языка, который можно было бы определить в терминах ядра языка, состоящего из основных конструкций; удобные, более высокоуровневые возможности можно было бы «разсахарить» и разложить на это подмножество. Это, по сути, стандартная математическая практика построения из примитивов. Развивая различие, сделанное Лэндином между основными языковыми конструкциями и синтаксическим сахаром, в 1991 году Маттиас Феллейзен предложил кодификацию «выразительной силы» для согласования с «общепринятыми представлениями» в литературе. Он определил «более выразительным» как то, что без рассматриваемых языковых конструкций программу пришлось бы полностью перестраивать.
Примечательные примеры
В COBOL многие промежуточные ключевые слова являются синтаксическим сахаром, который можно необязательно опустить. Например, предложение `MOVE A B.` и предложение `MOVE A TO B.` выполняют точно такую же функцию, но второе делает выполняемое действие более понятным. Операторы расширенного или составного присваивания: например, `a += b` эквивалентно `a = a + b` в C и подобных языках, при условии, что `a` не имеет побочных эффектов, например, если `a` является обычной переменной. Некоторые языки, такие как Python, могут допускать перегрузку операторов расширенного присваивания, поэтому они могут вести себя иначе, чем стандартные. В Perl, `unless (condition) { }` является синтаксическим сахаром для `if (not condition) { }`. Кроме того, любое выражение может следовать за условием, поэтому `statement if condition` эквивалентно `if (condition) { statement }`, но первое более естественно форматируется в одну строку. В языке C обозначение `a[i]` является синтаксическим сахаром для `*(a + i)`. Аналогично, обозначение `a->x` является синтаксическим сахаром для доступа к членам с использованием оператора разыменования (`*a`).x. В C# оператор `using` гарантирует правильную утилизацию определенных объектов. Компилятор преобразует этот оператор в блок `try...finally`. Язык C# позволяет объявлять переменные как `var x = expr`, что позволяет компилятору выводить тип `x` из выражения `expr`, вместо того, чтобы требовать явного объявления типа. Аналогично, C++ позволяет использовать `auto x = expr` начиная с C++11, а Java – `var x = expr` начиная с Java 11. В Python – списочные выражения (например, `[x*x for x in range(10)]` для списка квадратов) и декораторы (например, `@staticmethod`). В Haskell строка, заключенная в кавычки, семантически эквивалентна списку символов. Дополнительное расширение языка `OverloadedStrings` позволяет строковым литералам создавать значения других типов, например `Text`. В коллекции пакетов tidyverse для R, пайп (обозначается `%>%`) указывает, что данные (или результат функции), предшествующие пайпу, будут служить первым аргументом для функции, следующей за пайпом. Таким образом, `x %>% f(y)` эквивалентно `f(x, y)`. В SQL простое `JOIN` эквивалентно `INNER JOIN`, последнее уточняет, что оператор соединения является конкретно внутренней операцией соединения, а не внешней. Аналогично, можно опустить `OUTER` из `LEFT OUTER JOIN`, `RIGHT OUTER JOIN` и `FULL OUTER JOIN`. Вызов метода в объектно-ориентированных языках в форме `myObject.myMethod(parameter1, parameter2, parameter3)` является синтаксическим сахаром для вызова глобальной функции как `myMethod(myObject, parameter1, parameter2, parameter3)`. Ссылка на объект передается как скрытый аргумент, обычно доступный внутри метода как `this`. Параметр, передаваемый по ссылке, является синтаксическим сахаром для фактической передачи указателя в качестве параметра, но синтаксически обрабатывается как сама переменная, чтобы избежать постоянного разыменования указателя в коде внутри функции. В Java объявление `import` позволяет компилятору находить классы, которые не указаны в других случаях с использованием полных имен. Например, `import javax.swing.*;` позволяет программисту ссылаться на объект Swing, такой как `javax.swing.JButton`, используя более короткое имя `JButton`. В версии ES6 JavaScript стрелочные функции имеют короткую форму `(x) => x + 1`, которая эквивалентна более длинной форме `(x) => { return x + 1; }`. В Scala тройные вопросительные знаки (`???`) эквивалентны `throw new NotImplementedError`. Это полезно для обозначения места для кода, который еще не был написан.
Критика
Некоторые программисты считают, что эти элементы удобства синтаксиса либо неважны, либо откровенно легкомысленны. В частности, специальные синтаксические конструкции делают язык менее единообразным, а его спецификацию – более сложной, и могут создавать проблемы по мере роста и усложнения программ. Эта точка зрения особенно распространена в сообществе Lisp, поскольку Lisp обладает очень простым и регулярным синтаксисом, и поверхностный синтаксис может быть легко модифицирован. Например, Алан Перлис однажды остроумно заметил в "Эпиграммах о программировании", ссылаясь на языки с использованием скобок, что "Синтаксический сахар вызывает рак точек с запятой".
Синтаксическая соль
Эта метафора была расширена введением термина "синтаксическая соль", обозначающего особенность, призванную затруднить написание некачественного кода. В частности, синтаксическая соль – это препятствие, которое программистам необходимо преодолеть, чтобы продемонстрировать понимание происходящего, а не просто выразить действие программы. В C#, при сокрытии унаследованного члена класса, компилятор выдает предупреждение, если не используется ключевое слово `new` для явного указания намеренного сокрытия. Чтобы избежать потенциальных ошибок, связанных с синтаксическим сходством оператора `switch` с языками C или C++, в C# требуется оператор `break` для каждой непустой метки `case` (если не используются `goto`, `return` или `throw`), даже несмотря на то, что не допускается неявное проваливание в следующий `case`. (Использование `goto` и указание следующей метки обеспечивает поведение, аналогичное проваливанию в C/C++.) Синтаксическая соль может свести на нет свою полезность, делая код трудночитаемым и, следовательно, ухудшая его качество – в крайних случаях, основная логика кода может оказаться короче, чем накладные расходы, необходимые для соответствия требованиям языка. Альтернативой синтаксической соли является генерация предупреждений компилятором при высокой вероятности того, что код является результатом ошибки – практика, широко распространенная в современных компиляторах C/C++.
Синтаксический сахарин
Другие расширения — синтаксический сахарин и синтаксический сироп, то есть излишний синтаксис, который не упрощает программирование.
Сахарные сорта
Типы данных с основной синтаксической поддержкой называются "типами с синтаксическим сахаром". Распространенные примеры включают строки, заключенные в кавычки, фигурные скобки для объектов и записей, и квадратные скобки для массивов.