В чем разница между «синтаксисом» и «синтаксическим сахаром»

45

Фон

На странице Википедии о синтаксическом сахаре говорится:

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

Я не очень понимаю, в чем разница между синтаксическим сахаром и синтаксисом.

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

С той же страницы Википедии:

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

В качестве упражнения для размышления, если я принимаю слово «часто» в этом выражении как «всегда»: если бы разница заключалась лишь в том, «компилирует ли» компилятор синтаксис перед переходом к следующему этапу, как мог бы кодер, который не знает внутренностей компилятора знают (или заботятся), что такое синтаксис Sugar'd или нет?

Очень связанный вопрос на этом сайте "Строгое определение синтаксического сахара?" имеет ответ, который начинается:

ИМХО, я не думаю, что у вас может быть определение для синтаксического сахара, потому что эта фраза написана на BS и, вероятно, будет использоваться людьми, которые говорят о «настоящих программистах», использующих «настоящие инструменты» в «реальных операционных системах»

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

Суть вопроса

Итак ... краткая версия вопроса:

  • Есть ли реальная разница между синтаксисом и синтаксическим сахаром?
  • Для кого это важно?

Дополнительная пища для размышления

Бонус на противоречие темы:

На странице Википедии приведен пример:

Например, в языке C a[i]обозначение является синтаксическим сахаром для*(a + i)

Принимая во внимание, что другой ответ на вышеупомянутый связанный вопрос говорит о том же примере:

Теперь посмотрим a[i] == *(a + i). Подумайте о любой программе на C, которая использует массивы любым существенным образом.

И резюмирует, что:

[]Обозначения облегчает эту абстракцию. Это не синтаксический сахар.

Обратный вывод к тому же примеру!

Дон винс
источник
9
В своем ответе на процитированный вопрос я объясняю, что синтаксический сахар - это альтернативный синтаксис (некоторому синтаксису, который уже существует в языке), который облегчает выражение некоторых распространенных идиом, но не вводит новую семантику. В этом смысле синтаксический сахар зависит от контекста (от языка, на котором он используется): одна и та же нотация может быть обычным синтаксисом на одном языке и синтаксическим сахаром на другом языке. Поможет ли вам это объяснение?
Джорджио
7
Одна проблема состоит в том, что некоторые люди думают, что «синтаксический сахар» - это грязное слово, когда это не так. Каждая функция или класс, который вы добавляете в систему, может считаться «синтаксическим сахаром», так как они делают идеи, которые были явно уже выражены в языке, немного (или намного) проще для выражения.
Йорис Тиммерманс
Видимо, это важно для вас.
SShaheen
11
В конце концов, это всего лишь синтетический сахар, а не электричество.
Энтони Пеграм

Ответы:

34

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

На практике синтаксический сахар используется только для описания синтаксиса, добавляемого в язык для облегчения использования, например, для создания инфиксной lhs + rhsкарты lhs.Add(rhs). Я бы посчитал индексирование массива C синтаксическим сахаром.

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

Telastyn
источник
«Как только вы доберетесь до этой функциональности, любой другой синтаксис, который позволяет вам делать то же самое, будет считаться сахаром». Этого недостаточно, чтобы иметь синтаксический сахар, потому что тогда любая другая программа, которая вычисляет ту же функцию, будет синтаксическим сахаром. , Программа с сахаром и без сахара должна иметь одинаковую семантику .
Джорджио
3
@ Джорджио Как «эти две программы вычисляют одну и ту же функцию», в отличие от «эти две программы имеют одинаковую семантику»? Кроме того, вы сосредоточены на программах, а не на синтаксических элементах. Целые программы не могут быть синтаксическим сахаром. Оператор, своего рода оператор и т. Д. Могут быть синтаксическим сахаром.
@ Джорджио - Действительно, я рассматриваю схожую функциональность с различной семантикой как другую функциональность. И да, может быть прыжок с обручем, как если бы вы написали свой собственный компилятор с такой же семантикой и назвали этот «сахар». Честно говоря, формального определения для такого неформального понятия не произойдет.
Теластин
1
@ Джорджио Опять же, моя претензия связана не с вашей оценкой эквивалентности, а с попыткой применить концепцию синтаксического сахара к программам. Термин не относится ко всем программам! В зависимости от вашего определения, это либо только атомарные строительные блоки, либо только короткие фрагменты программы (первый, кажется, охватывает> 80%, но я не уверен, что он охватывает все, что обычно считается синтаксическим сахаром).
3
@ Джорджио Например, целые программы ;-) Или что-нибудь достаточно большое, чтобы обе формулировки включали несколько несвязанных ключевых слов языка. То, что я никогда не воспринимал как синтаксический сахар, if (a) return blah; ...против result_type res; if (a) res = blah; else {...}; return res;. Чтобы найти разницу между этими программами, вам нужно было бы использовать определенные языки и использовать исключительно language-lawyer-y (часто с точки зрения мелкомасштабной операционной семантики).
10

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

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

Чтобы дать более формальное определение, я бы сказал,

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

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

Барт ван Инген Шенау
источник
«Невозможно однозначно сказать« это синтаксический сахар и это синтаксис », потому что синтаксический сахар является частью синтаксиса языка». False. Это конструктор языка, который вводит некоторый синтаксис в качестве синтаксического сахара для некоторой конструкции, которая уже есть в языке и имеет синтаксис. Синтаксический сахар обычно является специальным (менее общим), но более читаемым / удобным в использовании.
Джорджио
@ Джорджио: Я перефразировал свой первый абзац, так как это было немного неловко. Но я не согласен с тем, что синтаксический сахар обычно добавляется нерегулярно. Вероятно, наиболее известным синтаксическим сахаром является ->оператор Си, и я не вижу, как этот оператор менее общий, чем любой другой.
Барт ван Инген Шенау
1
@ Джорджио: В этом случае все, что не отображается напрямую в одну инструкцию по сборке, следует рассматривать как синтаксический сахар, потому что оно всегда может быть разбито на более простые части (включая функции). Я не думаю, что вы не найдете много людей, разделяющих эту точку зрения.
Барт ван Инген Шенау
1
«Ad-hoc» означает, что он используется в особой, ограниченной ситуации. Термин не имеет отрицательного значения в целом. Термин специальное решение имеет отрицательную коннотацию, потому что обычно требуется общее решение, а не конкретное (чтобы избежать повторения подобных проблем снова и снова).
Джорджио
1
Поскольку «специальные решения» часто бывают плохими, может показаться, что «специальные решения» сами по себе означают плохие. Но есть также перегрузка функции «специального полиморфизма» AKA ( en.wikipedia.org/wiki/Ad_hoc_polymorphism ), что неплохо. По крайней мере, на итальянском (мой родной язык) использование латинского «ad-hoc» само по себе не является негативным. Если это имеет отрицательный оттенок в английском, то простите мое невежество.
Джорджио
6

Другие ответы не упомянули ключевую концепцию: абстрактный синтаксис ; без этого термин «синтаксический сахар» не имеет никакого смысла.

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

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

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

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

Итак, разница между «синтаксическим сахаром» и «конкретным синтаксисом» теперь очевидна. Мне. :)

Эта интерпретация также помогает объяснить, что Алан Перлис мог иметь в виду, когда говорил «синтаксический сахар вызывает рак точки с запятой»: весь конкретный синтаксический сахар в мире не может исправить слабый абстрактный синтаксис, и все усилия, которые вы тратите, добавляя, что сахар усилия, которые вы не тратите на решение реальной проблемы - абстрактного синтаксиса.


Я должен также отметить, что это исключительно мое мнение; Я верю в это только потому, что это единственная интерпретация, которую я могу придумать, которая имеет смысл для меня.


источник
1
Я также думал о сравнении абстрактного и конкретного синтаксиса, но я не уверен, что это всегда объясняет синтаксический сахар. Например, в C, учитывая указатель pна структуру, содержащую поле x, выражения (*p).xи p->xимеют ли тот же абстрактный синтаксис? Но я думаю, было бы здорово, если бы все сводилось к абстрактному или конкретному синтаксису.
Джорджио
@ Джорджио, к сожалению, я не знаю достаточно C, чтобы уверенно утверждать, является ли один из них синтаксическим сахаром для другого, или как будут выглядеть их абстрактные синтаксические деревья. Или даже если спецификация C фактически определяет абстрактный синтаксис. :(
1
Первое выражение может быть проанализировано как дерево с .корнем в корне. Левый подузел корня - это *, а его дочерний - p. Правый подузел корня есть x. Для второго выражения абстрактное синтаксическое дерево имеет ->корень а, а корень имеет двух дочерних элементов pи x. Я пытаюсь выяснить, имеет ли смысл анализировать оба выражения по-разному, чтобы они имели одно и то же абстрактное синтаксическое дерево, но пока не вижу, как это сделать.
Джорджио
3
Я не думаю, что это дерево разбора, даже если его часто называют AST, совпадает с абстрактным синтаксисом, о котором говорит Мэтт. Оба выражения имеют одинаковое действие ( преобразовать тип указателя в ссылочный тип, а затем получить ссылку на членx )
бесполезно
1
«Оба выражения имеют одинаковое действие (преобразовать тип указателя в ссылочный тип, а затем получить ссылку на член x)»: это семантика, а не абстрактный синтаксис. Под абстрактным синтаксисом подразумевается исключение ненужных подробностей конкретного синтаксиса (например, (или ;) для создания дерева, отражающего фактическую структуру программы (см. En.wikipedia.org/wiki/Abstract_syntax_tree ). Однако в абстрактном синтаксисе ничего не сказано (пока) о семантике программы.
Джорджио
4

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

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

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

На практике именно так решается реальность вопроса.

Джефф Вольски
источник
Этот ответ неверно связывает реализацию синтаксиса с тем, является ли он сахаром или нет. Я никогда не видел аргументов о том, является ли элемент языка «сахарным» или нет, который касается того, как этот элемент реализован. Это просто о том, дублирует ли он синтаксически другой, более уродливый элемент.
GreenAsJade
3

Действительно, ваша первая цитата из Википедии гласит, что все "... облегчает чтение ...", ".... людям приятнее пользоваться ....".

В письменной форме укороченные формы, такие как «не» или «не», могут считаться синтаксическим сахаром.

Ozz
источник
Рассмотрим (1) «Я должен идти сейчас» против (2) «Я должен идти сейчас»: является ли (1) синтаксическим сахаром для (2)?
Джорджио
1
@ Джорджио, я бы сказал нет.
Оз
Из-за читабельности («должен» не более читабелен, чем «должен») или из-за значения («должен» и «должен» иметь разные значения).
Джорджио
@ Giorgio достаточно справедливо :)
ozz
1
Ах, я понимаю :), мне кажется, что это более
интуитивно
3

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

Например, у Haskell есть синтаксический сахар для монад с рекурсивным применением следующих правил

do { f }            ~> f
do { g; h }         ~> g >> do h
do { x <- f; h }    ~> f >>= \x -> do h
do { let x = f; h } ~> let x = f in do h

Прямо сейчас не имеет значения, что именно это означает - однако вы можете видеть, что специальный синтаксис в LHS может быть преобразован во что-то более базовое в RHS (а именно, приложения функций, лямбды и т. Д. let). Этот шаг позволяет сохранить лучшее из обоих миров:

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

Точно так же в C вы можете представить себе правило перезаписи desugaring (из-за перегрузки операторов и т. Д. Это не так для C ++):

f->h ~> (*f).h
f[h] ~> *(f + h)

Вы можете представить, что пишете все программы без использования ->или []в C, которые используют эту конструкцию сегодня. Однако программистам было бы сложнее использовать его, поэтому он предоставил синтаксический сахар (я думаю, в 70-х годах это могло бы упростить работу и для компиляторов). Возможно, это менее понятно, поскольку вы можете технически добавить следующее, совершенно правильное правило переписывания:

*f ~> f[0] -- * and [] have the same expressiveness 

Синтаксис сахара плох? Не обязательно - есть опасность, что он будет использоваться как культ груза, не понимая более глубокого смысла. Например, следующие функции эквивалентны в Haskell, но многие начинающие пишут первую форму, не понимая, что они злоупотребляют синтаксическим сахаром:

f1 = do x <- doSomething
        return x
f2 = doSomething

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

Мацей Печотка
источник
3

Я думаю, что наиболее очевидным примером будет синтаксис "+ =" в C.

i = i + 1;

а также

 i +=  1;

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

Я собирался привести оператор ++ / префикс «++» в качестве канонического примера, но понял, что это было больше, чем синтаксический сахар. Невозможно выразить разницу между ++ i и i ++ в одном выражении с использованием i = i + 1синтаксиса.

Джеймс Андерсон
источник
+ = может пригодиться в таких случаях, как a[f(x)] += 1.
Флориан Ф
1

Сначала я приведу некоторые другие ответы на конкретном примере. Цикл for в C ++ 11 (очень похож на циклы foreach в других языках)

for (auto value : container) {
    do_something_with(value);
}

в точности эквивалентно (то есть, засахаренная версия)

for (auto iterator = begin(container); iterator != end(container); ++iterator) {
    do_something_with(*iterator);
}

Теперь, несмотря на отсутствие нового абстрактного синтаксиса или семантики в языке, он действительно полезен.

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

Например, односимвольная ошибка во второй версии:

for (auto iterator = begin(container); iterator <= end(container); ++iterator) {
    do_something_with(*iterator);
}

дает ошибку «один за другим» и неопределенное поведение.

Таким образом, версия с сахаром полезна именно потому, что она более ограничительна и, следовательно, проще доверять и понимать.


Во-вторых, к первоначальному вопросу:

Есть ли реальная разница между синтаксисом и синтаксическим сахаром?

Нет, «синтаксический сахар» - это (конкретный) синтаксис языка, который считается «сахаром», потому что он не расширяет абстрактный синтаксис или основные функциональные возможности языка. Мне нравится ответ Мэтта Фенвика на это.

Для кого это важно?

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

Наконец, о бонусном вопросе

Запись [] облегчает эту абстракцию.

это очень похоже на определение синтаксического сахара: оно поддерживает (и предоставляет благословение авторов языка) использование указателей в качестве массивов. p[i]Форма на самом деле не более ограничительная , чем *(p+i), поэтому единственное отличием является четкой связью намерения (и небольшой выигрыш читаемости).

Бесполезный
источник
Сначала вы говорите: «[диапазон, основанный на цикле] в точности эквивалентен (то есть, засахаренной версии) [что-то другое]». Но затем вы говорите, что это по-другому, в том смысле, что он запрещает модифицировать контейнер во время обхода ... и есть другие различия, которые делают его не просто описанным вами простым синтаксическим преобразованием (например, поведение, когда «контейнер» является временным). Эти различия подразумевают, что это не просто синтаксический сахар, верно? Поэтому мне кажется, что это не хороший пример синтаксического сахара.
Дон Хэтч
Я не сказал, что это эквивалентно какому-то общему циклу , я сказал, что это эквивалентно конкретному заданному циклу. Конкретный цикл не изменял контейнер, и представляет собой очень распространенную идиому - но вам все еще нужно внимательно прочитать каждый общий цикл , чтобы сказать , является ли он после этой общей идиомы, или если что - то необычное таится в теле цикла. Более новая петля - сахар для этой общей идиомы , поскольку она менее многословна и более четко передает используемую идиому. Это не так, и я никогда не утверждал, что это так или иначе является сахаром для общей идеи цикла.
бесполезно
0

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

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

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

Карл Билефельдт
источник
Я думаю, что уничижительное значение термина («это только синтаксический сахар») происходит от того факта, что синтаксический сахар не добавляет никакой информации.
Джорджио
1
Это может быть связано с идеей, что синтаксис не добавляет никакой информации , но эта идея не является фактом. Информация о намерении (например, использовать общеизвестную идиому) по-прежнему является информацией.
бесполезно
@ Бесполезно: Под информацией я подразумевал, что программа ведет себя одинаково с синтаксическим сахаром или без него. Конечно, он может быть более читабельным с синтаксическим сахаром (он добавляет информацию / документацию для читателя), что является преимуществом.
Джорджио
Богус. Синтаксический сахар не является уничижительным. Любой программист, достойный его или ее соли, создаст библиотеки, которые инкапсулируют и упрощают более сложные задачи, а не копируют и вставляют один и тот же код повсюду. Это приводит к тому, что код становится лучше и удобнее в обслуживании. По сути, это то, что синтаксический сахар выполняет путем абстрагирования общих, хотя и сложных, шаблонов в более простой синтаксис.
Крейг
Я говорю, что люди обычно называют этот термин оскорблением, я не комментирую саму основную практику. Сказать, что слово «идиот» является оскорбительным, не означает, что все люди идиоты. Когда люди хотят говорить о практике позитивно, они обычно используют такие термины, как «абстракция» или «инкапсуляция».
Карл Билефельдт