46

Background

The Wikipedia page on Syntactic Sugar states:

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 humans to use: things can be expressed more clearly, more concisely, or in an alternative style that some may prefer.

I don't really understand what the difference is between Syntactic Sugar and Syntax.

I appreciate the point that the sugary version can be clearer, more concise, perhaps boil off some boilerplate. But I feel at some level, all the syntax is essentially doing that to form an abstraction over what the code gets compiled down to.

From the same Wikipedia page:

Language processors, including compilers, static analyzers, and the like, often expand sugared constructs into more fundamental constructs before processing, a process sometimes called "desugaring".

As a thought exercise, if I take "often" in this statement to mean "always": If the difference were just whether the compiler "desugars" the syntax before moving to a next stage, how might a coder who does not know the innards of the compiler know (or care) what is Sugar'd Syntax or not?

A very much related question on this site "Rigorous Definition of Syntactic Sugar?" has an answer which commences:

IMHO I don't think you can have a definition for syntactic sugar, because the phrase is BS and is likely to be used by people that talk about "real programmers" using "real tools" on "real operating systems"

Which might indicate to me that perhaps there isn't a huge difference to the coder using the language? Perhaps the difference is only perceptible to the compiler writer? Though there may be instances in which it's helpful for the coder using the language to know what's under the hood of the Syntactic Sugar? (But perhaps in reality any discourse on the subject tends to use the term as flame bait?)

The heart of the question

So... the short version of the question:

  • Is there a real difference between Syntax and Syntactic Sugar?
  • Who does it matter to?

Extra Food for Thought

Bonus on topic contradiction:

On the Wikipedia page an example is given:

For instance, in the C language the a[i] notation is syntactic sugar for *(a + i)

Whereas another answer on the above linked question talks about the same example:

Now consider a[i] == *(a + i). Think about any C program that uses arrays in any substantive way.

And summarizes that:

The [] notation facilitates this abstraction. It's not syntactic sugar.

The opposite conclusion for the same example!

4
  • 9
    In my answer to the cited question I explain that syntactic sugar is an alternate syntax (to some syntax that already exists in the language) that makes it easier to express some common idioms but does not introduce new semantics. In this sense, syntactic sugar depends on the context (on the language in which it is used): the same notation can be normal syntax in one language, and syntactic sugar in another language. Does this explanation help you?
    – Giorgio
    Apr 5, 2013 at 13:29
  • 7
    One problem is that some people seem to think "syntactic sugar" is a dirty word, when it isn't. Each function or class you add to a system could be considered "syntactic sugar", since they make ideas that were clearly already expressible in the language a little bit (or a lot) easier to express. Apr 5, 2013 at 13:44
  • Apparently, it matters to you.
    – SShaheen
    Apr 5, 2013 at 17:57
  • 12
    In the end, it's all just syntatic sugar over electricity. Apr 5, 2013 at 20:47

9 Answers 9

34

The main difference is that syntax is grammar defined in a language to allow you to expose some functionality. As soon as you could get to that functionality, any other syntax that lets you do the same thing is considered sugar. That of course runs into odd scenarios about which of the two syntaxes is the sugar, especially since it's not always clear which came first.

In practice, syntactic sugar is only used to describe syntax added to a language to facilitate ease of use, like making infix lhs + rhs map to lhs.Add(rhs). I would consider C's array indexing to be syntactic sugar.

It matters mostly because elegant designs tend to limit the amount of duplication. Needing (or at least wanting) syntactic sugar is seen by some as a sign of a design failing.

11
  • "As soon as you could get to that functionality, any other syntax that lets you do the same thing is considered sugar.": This is not enough to have syntactic sugar, because then any other program that computes the same function would be syntactic sugar. The sugared and the de-sugared program must have the same semantics.
    – Giorgio
    Apr 5, 2013 at 13:42
  • 3
    @Giorgio How's "these two programs compute the same function" different from "these two programs have the same semantics"? Aside from that, you're focusing on programs, not on syntactic elements. Whole programs can't be syntactic sugar. An operator, a kind of statement, etc. can be syntactic sugar.
    – user7043
    Apr 5, 2013 at 14:20
  • @Giorgio - Indeed, I am considering similar functionality with different semantics to be different functionality. And yeah, there could be hoop jumping like writing your own compiler that has the same semantics and calling that "sugar". Frankly, a formal definition is not going to happen for such an informal concept.
    – Telastyn
    Apr 5, 2013 at 14:29
  • 1
    @Giorgio Again, my beef is not with your take on equivalence, but that you try and apply the concept of syntactic sugar to programs. The term does not refer to whole programs! Depending on your definition, it's either only atomic building blocks, or only short program fragments (the first seems to cover >80%, but I'm not sure that it covers everything commonly considered syntactic sugar).
    – user7043
    Apr 5, 2013 at 14:48
  • 3
    @Giorgio For example, whole programs ;-) Or anything large enough that both formulations involve several unrelated language keywords. Something that I've never been treated as syntactic sugar is if (a) return blah; ... versus result_type res; if (a) res = blah; else {...}; return res;. You'd need to assume specific languages, and get extremely language-lawyer-y (often to the point of small-step operational semantics), to find any difference between those programs.
    – user7043
    Apr 5, 2013 at 15:02
10

Syntax is what a language processor uses to understand what the constructs of a language mean. Constructs that are deemed to be syntactic sugar also have to be interpreted by the language processor and thus are part of a languages syntax.

That what sets syntactic sugar apart from the rest of the syntax of a language is that it would be possible to remove the syntactic sugar from the language without affecting the programs that can be written in the language.

To give a more formalistic definition, I would say

Syntactic sugar are those parts of a language's syntax whose effects are defined in terms of other syntax constructs in the language.

This is in no way meant to denigrate syntactic sugar, or the languages that have it, because the use of syntactic sugar often leads to programs whose intent is more understandable.

13
  • "There is no way to definitively say 'this is syntactic sugar and that is syntax', because syntactic sugar is part of the syntax of a language.": False. It is the language designer that introduces some syntax as syntactic sugar for some construct that is already in the language and has a syntax. The syntactic sugar is normally ad-hoc (less general) but more readable / convenient to use.
    – Giorgio
    Apr 5, 2013 at 13:39
  • @Giorgio: I rephrased my first paragraph as it was a bit awkward. But I don't agree that syntactic sugar is normally added ad-hoc. The most widely known bit of syntactic sugar is probably C's -> operator and I don't see how that operator is less general than any of the others. Apr 5, 2013 at 13:52
  • 1
    @Giorgio: In that case, everything that does not map directly to a single assembly instruction should be regarded as syntactic sugar, because it could always be broken down into simpler pieces (this includes functions). I don't think you will not find many people sharing that view. Apr 5, 2013 at 14:08
  • 1
    "Ad-hoc" means that it is used in a special, restricted situation. The term does not have a negative connotation in general. The term ad-hoc solution does have a negative connotation, because one normally wants general solutions, not particular ones (to avoid solving similar problems again and again).
    – Giorgio
    Apr 5, 2013 at 14:31
  • 1
    Since "ad-hoc solutions" are often bad, it may seem that "ad-hoc" itself means bad. But there is also "ad-hoc polymorphism" AKA function overloading (en.wikipedia.org/wiki/Ad_hoc_polymorphism), which is not bad. At least in Italian (my mother tongue), the use of the Latin "ad-hoc" is not negative in itself. If it does have a negative connotation in English, then pardon my ignorance.
    – Giorgio
    Apr 5, 2013 at 18:48
6

The other answers haven't mentioned a key concept: abstract syntax; without it, the term "syntactic sugar" doesn't make any sense.

Abstract syntax defines the elements and structure of languages, and how phrases of that language can be combined to build bigger phrases. Abstract syntax is independent of concrete syntax. The term "syntactic sugar", as I understand it, refers to concrete syntax.

In general, when designing a language, you'll want to create concrete syntax for each term of your abstract syntax, so that people can write code in your language using plain text.

Now let's say you create an awkward concrete syntax for foo. Users complain, and you implement a new concrete syntax to represent the same abstract syntax. The result is that your abstract syntax and semantics haven't changed, but you now have two concrete syntaxes for the same abstract syntax term.

This, I believe, is what people mean when they say "syntactic sugar" -- changes which only affect concrete syntax, but which do not affect abstract syntax or semantics.

And so the difference between "syntactic sugar" and "concrete syntax" is now clear. To me. :)

This interpretation also helps explain what Alan Perlis might have meant when he said "syntactic sugar causes cancer of the semicolon": all the concrete syntactic sugar in the world can't fix weak abstract syntax, and all the effort you expend adding that sugar is effort you aren't spending dealing with the real problem -- the abstract syntax.


I should also note that this is solely my opinion; I only believe it because it's the only interpretation I can think of that makes sense to me.

11
  • 1
    I had also thought about the comparison abstract versus concrete syntax but I am not sure that this always explains syntactic sugar. E.g., in C, given a pointer p to a struct containing a field x, do the expressions (*p).x and p->x have the same abstract syntax? But I think it would be great if everything boiled down to abstract versus concrete syntax.
    – Giorgio
    Apr 5, 2013 at 15:19
  • @Giorgio unfortunately, I don't know enough C to confidently state whether either of those is syntactic sugar for the other, or what their abstract syntax trees would look like. Or even if C's spec actually defines an abstract syntax. :(
    – user39685
    Apr 5, 2013 at 15:26
  • 1
    The first expression can be parsed as a tree with a . at the root. The left subnode of the root is a *, and its child is p. The right subnode of the root is x. For the second expression, the abstract syntax tree has a -> at the root and the root has two children p and x. I am trying to figure out if it makes sense to parse both expressions differently so that they have the same abstract syntax tree, but I do not see how at the moment.
    – Giorgio
    Apr 5, 2013 at 15:36
  • 3
    I don't think this parse tree, even if often described as an AST, is the same as the abstract syntax Matt is talking about. Both expressions have the identical action (convert pointer type to reference type, then get reference to member x)
    – Useless
    Apr 5, 2013 at 15:40
  • 1
    "Both expressions have the identical action (convert pointer type to reference type, then get reference to member x)": This is semantics, not abstract syntax. Abstract syntax refers to leaving out useless details of the concrete syntax (like ( or ;) to produce a tree that reflects the actual structure of a program (see en.wikipedia.org/wiki/Abstract_syntax_tree). However, in abstract syntax nothing is said (yet) about the program's semantics.
    – Giorgio
    Apr 5, 2013 at 15:49
4

Syntactic sugar is a subset of the languages syntax. The basic idea is that there is more than one way to say the same thing.

What makes it difficult to say which pieces are syntactic sugar and which pieces are "pure syntax" are statements like "it's hard to say which form came first" or "it's hard to know which way the author of the language intended" or "it's somewhat arbitrary to decide which form is simpler".

What makes it easy to decide which pieces are pure or sugary are to ask the question within the frame of a specific compiler or interpreter. The pure syntax is the stuff that a compiler converts directly to machine-code or that the interpreter directly responds to. The sugar is the stuff that first gets turned into some other syntax stuff before these direct things happen. Depending on the implementation, this may or may not be the same as what the author intended or even what the language spec claims.

In practice, this is the way that the reality of the matter is decided.

1
  • This answer wrongly connects the implementation of the syntax to whether it is sugar or not. I've never seen an arguments= about whether an element of a language is "sugar" or not that concerns itself with how the element is implemented. It's purely about whether it duplicates a different, uglier, element, syntactically. Aug 16, 2014 at 0:43
3

Really, your first quote from Wikipedia says it all "...makes things easier to read...", "....sweeter for humans to use....".

In writing, shortened forms such as "don't" or "haven't" could be considered syntactic sugar.

6
  • Consider (1) "I should go now" versus (2) "I ought to go now": Is (1) syntactic sugar for (2)?
    – Giorgio
    Apr 5, 2013 at 15:23
  • 1
    @Giorgio I'd say no.
    – ozz
    Apr 5, 2013 at 16:49
  • Because of readability ("should" is not more readable than "ought to") or because of meaning ("should" and "ought to" have different meanings).
    – Giorgio
    Apr 5, 2013 at 16:56
  • @Giorgio fair enough :)
    – ozz
    Apr 5, 2013 at 17:00
  • 1
    Ah I see :) more of a gut feel I guess, I don't think one is more readable than the other in that example
    – ozz
    Apr 5, 2013 at 17:38
3

Usually syntax sugar is the part of language that can be expressed by existing part of language (syntax) without loss of generality but with possibly lossing clarity. Sometimes the compilers have explicit desugaring step which transforms the AST created by the source code and apply simple steps to remove nodes corresponding to sugar.

For example Haskell have syntax sugar for monads with following rules applied recursivly

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

Right now it doesn't matter what it means exactly - however you can see that special syntax on LHS can be transformed into something more basic on RHS (namely function applications, lambdas and let's). This steps allows to keep best of both worlds:

  1. The syntax on LHS is easier for programmer (syntax sugar) expressing the existing ideas in more clear manner
  2. However as the support in compiler for RHS constructs do exists already in compiler it doesn't need to treat it as something special outside parser and desugaring (except for error reporting).

Similarly in C you can imagine desugaring rewrite rule (due to operator overloading etc. it is not true for C++):

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

You could imagine writing all programs without using -> or [] in C that use this construction today. However it would be harder for programmers to use it hence provided syntax sugar (I guess in 70's it might simplified work for compilers too). It is possibly less clear as you can technically add the following, perfectly valid, rewrite rule:

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

Is syntax sugar bad? Not necessarily - there is danger that it will be used as cargo cult without understanding deeper meaning. For example following functions are equivalent in Haskell yet many beginners would write the first form without understanding that they are overusing syntax sugar:

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

In addition syntax sugar might overcomplicate the language or be too narrow to allow generalized idiomatic code. Also it might mean that language is not powerful enough to do certain things easily - it might be by design (don't give developers sharp tools or very specific niche language that adding more powerful construct would hurt other goals) or by omission - the latter form gave the syntax sugar the bad name. If the language is powerful enough to use other constructs without adding syntax sugar it is considered more elegant to use those.

3

I think the most obvious example would be the "+=" syntax in C.

i = i + 1;

and

 i +=  1;

do exactly the same thing and compile to exactly the same set of machine instructions. The second form saves a couple of characters typing, but, more importantly makes it very clear that you are modifying a value based on its current value.

I was going to cite the "++" post/prefix operator as the canonical example but realized that this was more than syntactic sugar. There is no way to express the difference between ++i and i++ in a single expression using the i = i + 1 syntax.

1
  • 1
    += can be handy in cases like a[f(x)] += 1.
    – Florian F
    Sep 15, 2014 at 22:12
1

Whatever the original connotation of the phrase was, nowadays it is primarily a pejorative, almost always phrased as "just" or "only" syntactic sugar. It pretty much only matters to programmers who like to do things the unreadable way and want a concise way to justify that to their colleagues. A definition by those who primarily use the term today, from their point of view, would be something like:

Syntax that is redundant with other more widely applicable syntax, in order to provide a crutch for programmers who don't really understand the language.

That's why you get two opposite conclusions for the same syntactic element. Your first example on array notation is using the original positive meaning of the term, something similar to Bart's answer. Your second example is defending array notation against the charge of being syntactic sugar in the pejorative sense. In other words, it is arguing the syntax is a useful abstraction rather than a crutch.

6
  • I think the pejorative meaning of the term ("it is only syntactic sugar") comes from the fact that syntactic sugar does not add any information.
    – Giorgio
    Apr 5, 2013 at 14:58
  • 1
    It might come from the idea that syntactic does not add any information, but that idea isn't a fact. Information about intent (for example, to use a well-known idiom) is still information.
    – Useless
    Apr 5, 2013 at 15:02
  • @Useless: By information I meant a program behaves the same with or without syntactic sugar. Of course it can more readable with syntactic sugar (it adds information / documentation for the reader) which is an advantage.
    – Giorgio
    Apr 5, 2013 at 15:43
  • Bogus. Syntactical sugar is not a pejorative. Any programmer worth his or her salt will create libraries that encapsulate and simplify more complex tasks, rather than copy and paste the same code all over the place. This leads to better-behaved, more maintainable code. This is essentially what syntactic sugar accomplishes by abstracting common, though complex, patterns into simpler syntax. Dec 15, 2013 at 23:25
  • I'm saying that people usually mean the term as an insult, I'm not commenting on the underlying practice itself. Saying the word "idiot" is a perjorative doesn't imply all people are idiots. When people want to talk about the practice positively, they usually use terms like "abstraction" or "encapsulation." Dec 15, 2013 at 23:50
1

First, I'll address some of the other answers with a concrete example. The C++11 range-based for loop (much like foreach loops in various other languages)

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

is exactly equivalent to (ie, a sugared version of)

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

Now, despite adding no new abstract syntax or semantics to the language, it does have real utility.

The first version makes the intent (visiting every item in a container) explicit. It also prohibits unusual behaviour such as modifying the container during traversal, or further advancing iterator in the loop body, or getting the loop conditions subtly wrong. This avoids possible sources of bugs and, in doing so, reduces the difficulty of reading and reasoning about the code.

For example, a one-character mistake in the second version:

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

gives a one-past-the-end error and undefined behaviour.

So, the sugared version is useful precisely because it's more restrictive, and thus simpler to trust & understand.


Second, to the original question:

Is there a real difference between Syntax and Syntactic Sugar?

No, "syntactic sugar" is (concrete) language syntax, considered "sugar" because it doesn't extend the abstract syntax or core functionality of the language. I like Matt Fenwick's answer on this.

Who does it matter to?

It matters to users of the language, as much as any other syntax, and in that sugar is provided to support (and in some sense bless) specific idioms.

Finally, on the bonus question

The [] notation facilitates this abstraction.

this sounds a lot like the definition of syntactic sugar: it supports (and provides the language authors' blessing for) using pointers as arrays. The p[i] form isn't really more restrictive than *(p+i), so the only difference is the clear communication of intent (and a slight readability gain).

2
  • First you say "[the range based for loop] is exactly equivalent to (ie, a sugared version of) [some other thing]". But then you say it's different, in that it prohibits modifying the container during traversal... and there are other differences that make it more than just the simple syntactic transform you described (e.g. behavior when "container" is a temporary). These differences imply that it's not just syntactic sugar, right? So it seems to me maybe this isn't a good example of syntactic sugar.
    – Don Hatch
    Apr 28, 2016 at 0:30
  • I didn't say it was equivalent to some general loop, I said it was equivalent to the specific loop given. The specific loop does not modify the container, and represents a very common idiom - but you still need to read every general loop carefully to tell whether it's following that common idiom, or if something unusual is lurking in the loop body. The newer loop is sugar for that common idiom, being both less verbose and communicating more clearly the idiom in use. It is not, and I never claimed it was, somehow sugar for the general idea of a loop.
    – Useless
    Apr 28, 2016 at 12:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.