Syntactic Sugar

[But see GoodNotationIsValuable and ProgrammingLanguagesAreSyntacticSugar]

Constructs that have been added to a language in order to make life easier for programmers.

Very often, they improve writability a lot more than readability!

[One can argue both sides of the readability issue. Readability is sometimes one of the main justifications for SyntacticSugar.]

For reference, here's the JargonFile entry:

"[coined by PeterLandin] Features added to a language or other formalism to make it sweeter for humans, but which do not affect the expressiveness of the formalism (compare chrome). Used esp. when there is an obvious and trivial translation of the sugar feature into other constructs already present in the notation. C's a[i] notation is syntactic sugar for *(a + i). ?Syntactic sugar causes cancer of the semicolon.? -- AlanPerlis."

"The variants syntactic saccharin and syntactic syrup are also recorded. These denote something even more gratuitous, in that syntactic sugar serves a purpose (making something more acceptable to humans), but syntactic saccharin or syrup serve no purpose at all. Compare candygrammar, syntactic salt"

http://catb.org/~esr/jargon/html/S/syntactic-sugar.html

And for some context, a quote where the issue comes up in a serious context, by Larry Wall, from his Perl apocalypse 3 (http://www.perl6.org/archive/doc/design/apo/A03.html):

Whether one likes or hates Perl, I think this is a moderately neutral view of the trade-offs involved with SyntacticSugar in the domain where it is arguably most important: language design. Which choice you make will depend largely in how you weight the factors mentioned (which is partially a matter of taste).
Examples of SyntacticSugar (C/C++):
'X += 1' instead of 'X = X + 1'. They do the same thing, and if you have even the most minimal optimizing compiler, they'll produce the same code.
'instance1 + instance2' instead of 'instance1.operator+(instance2)' (or say 'instance1.plus(instance2)')
'for (i=0; i<10; ++i) {...}' instead of '{i=0; while (i<10) {...; ++i}}' or even 'for (0..9) { ... }'
References ('type &ver;') -- they give non-pointer syntax to things that are really pointers. (You could do all the same stuff with pointers, but it would be really annoying.)

You might be mistaken. 'for( 0..9 )' was not in C or C++ the last time I used them. Only the 'for( initializer; condition; loop-statement )' syntax is legal C/C++. My favourite example of SyntacticSugar is 'foreach( element in collection )', which is in C# and in PHP, with slightly different syntax. -- W2k

Actually, in PHP (I'm not sure about other languages) the foreach() syntax is foreach( $array as $key => $value ) so assuming you have used numbers as the key for $array, $key would be an index. Thus, you could refer to the current value of $array as either $array[ $key ] or as simply $value, inside the statement. Of course, you could use foreach( $array as $a_key => $this_value ) and refer to $array[ $a_key ] or $this_value. -- rd
x += 1 and x = x + 1 have different semantics when x is declared volatile - to me this says they are not equivalent, one is not syntactic sugar for the other.

But they don't differ in expressive power.

Perhaps not, but that is a non-sequitur. To be syntactic sugar the expressions must first be identical in semantics. If the semantics of two expressions are different then ipso facto neither can be syntactic sugar for the other. See the discussion on ExpressivePower for more.

The original claim was that x += 1 was syntactic sugar for x = x + 1. I replied that I do not believe that, because they have different semantics. To me, "syntactic" sugar requires "semantic equivalence", so since they have different semantics, neither is syntactic sugar for the other.

I believe your reference to expressive power is a non-sequitur.

-- anonX

I don't think so, because the difference in semantics is relatively trivial; in contexts where it is a completely inessential difference, they can be regarded as equivalent. -- dm

I'm writing a compiler and it's very, very far from trivial to me. It breaks some seriously good "optimizer" code, and I've had to develop some difficult code. To me, x++, x += 1, and x = x + 1 are very, very different semantically. I cannot see them as syntactic sugar and would argue that they are not. When two expressions lead to different behaviour for the brakes on your car, I believe it to be dangerous to refer to them as syntactic sugar. -- anonX

Creating problems for you is not necessarily the same as "very, very different semantically", that sounds like an exaggeration based on frustration. But it's been years since I worked on C++ compilers, so maybe I'm just forgetting; remind me which issues you're talking about. -- dm

The compiler I was using failed to compile volatile correctly and my code thus failed to apply the brakes in a traction control sub-system. I regard that as non-trivial, and it arose from the semantics. When using volatile the results on the machine between using x += 1 and x = x + 1 are different, it says so in the ANSI standard.

Here's my line of reasoning: Where does this fail for you? -- anonX

I am arguing that two constructs need not be absolutely semantically identical in order for one to be considered syntactic sugar for the other, just as sugar (loosely speaking) makes pastry from bread, but the bread and pastry are certainly not identical - the whole point is to create a difference.

Instead I would say that the two constructs need only be similar enough to be substitutable under some circumstances, not all circumstances. And maybe the relationship could be even looser than that.

PeterLandin's original definition as filtered through ESR in the jargon file is not very precise; perhaps the real question is, which precise definition would be most useful?

-- dm

Ah, so you go by the definition filtered through ESR which uses the term expressiveness, rather than the term itself which is "Syntactic Sugar". I read the term itself as implying that the semantics must remain untouched.

I believe this confusion is dangerous. In each case I've found bugs, in some cases some potentially very serious bugs, due to these confusions, and while to some extent it can be ascribed to poor programmer training, I believe at least in part it's due to the on-going inappropriate use of the term Syntactic Sugar.

I think the point is though, that these statements are logically congruent, Regardless of the fact that these sometimes generate different behavior. The implementation details of the compiler or language are completely separate from the fact that both terms represent "add 1 to the value of the variable x". The same can be said about any question of Syntactic Sugar - Are they different actions if you describe them in plain English? The answer in many cases is "not really". There are many ways of doing the same thing (referring to low-level processing), and no way is more correct than another.

Some things are not semantically identical, and I think that needs more emphasis. Especially for things like pointers and arrays in C.

So, as you ask, what is the correct definition of SyntacticSugar?

-- anonX (now getting off his hobby horse. Suggestions as to why the for and while loops are not identical are welcome.)

Suppose stuff; contains continue;.

I certainly agree that these kinds of confusion can be quite dangerous, but I'm not at all sure that it is the duty of the term SyntacticSugar to prevent them. :-)

I'll continue thinking about the most useful definition. I'm adding a real life example at top of page, a quote from Larry Wall, which I think helps with context, without itself offering such a definition. -- dm
Furthermore, it should be noted (in CeePlusPlus at least) one can use operator overloading to make x += 1 and x = x + 1 have completely different behavior.

Which of course is exactly what leads people to frown on operator overloading: using what is supposed to be syntactic sugar to create strongly inequivalent constructs.

I would add that in the context of operator overloadingb - even if you do it right to preserve the expected behavior - it is often more efficient to implement operator+= than operator+, because there are no temporary values involved in the first case.


Is X++ Syntactic Sugar?

I have to disagree with your first example. The C language was designed for systems work, of course, and in programming 'close to the metal' it was important to be able to represent many operations that essentially all CPU's shared, directly.

I disagree on first example as well. Sometimes the two constructions are not identical semantically. or differ if function_gives_ptr_to_int() has side-effects, or if it gives different values at each invocation. I would call that obscure coding, but the meanings are distinct. -- RobertField

I would call your example and abuse of syntax, not syntactic sugar. Of course a good compiler would be able to reduce both your examples to X++, but that is not the point. The act of incrementing a counter is different to that of assigning to a register, and in some CPU's incrementing by one is a special op. So in order to be able to do the appropriate thing, you need to either have a) an unbelievably smart compiler (especially for the time of C's design), or b) a way to tell the compiler what you want. Thus C needed an increment operator, and increment by some integer operator, and an assignment operator. What you see is not syntactic sugar, but the necessity of design.

OTOH, multiple equivalent loop structure are (IMO, very useful) syntactic sugar. This is the good kind, that can be used to improve readability.

-- AnonymousDonor

It's been argued (very effectively in my opinion ;-) that C/C++ syntax for ++X, X++, and *(p++) in particular were created so that a very limited C compiler could produce optimum PDP-11 code without an optimizer.

But now, with inlining optimizations considered an absolute minimum for acceptable C++ compiler features, I don't think these (or even 'register' declarations at this point) can really be considered compiler code generation hints any more. So I would call them SyntacticSugar at this point in time.

Really, I say that SyntacticSugar is a good thing, and that it normally improves the readability of the code. I could write "ADD ONE TO THIS-COUNTER GIVING THIS-COUNTER." (in COBOL), but I'd really rather write "++cntr;" I love SyntacticSugar; it makes my life easier.

-- JeffGrigg

The first example above concerns me. As was said, incrementing and assigning are inherently different operations. As I mentioned on CsharpVsJava, the idea of switching on a string, more syntactic sugar, disturbs me for the same reason. In exchange for saving a few keystrokes and, perhaps, more readibility, I am giving up my intuitive concept of how something works. Incrementing doesn't (always) work by assignment. Switching on a string doesn't use a jump table. While the net outcome may be the same, the efficiency of the techniques are very different; the sugar may save me a stroke when typing, but it misleads me, especially if I'm less than 100% familiar with the language, when reading. -- AdamBerger

The first example, "X = X + 1" can be expressed as "X += 1" or "X++" or "++X". The best way to express it depends on the thought you wish to express: If I wanted to "increment X", then I'd use "++X". (Others could reasonably use "X++", but I don't like that style.) If I wanted to "add one to X", then "X += 1" expresses the thought quite well. Even COBOL has special syntax that supports "ADD THIS-AMOUNT TO TOTAL." As for "X = X + 1", I have a hard time coming up with a clear English explanation as to what that's supposed to mean. -- JeffGrigg

That's the iterative definition:
  X(current) = X(previous) + 1

Sorry, but the use of pre-increment and post-increment have very specific applications in the C/C++ world. If one is dependent upon a value being incremented after an operation is performed then the post-increment is indicated. Blah, blah, blah. Let's not forget that C was originally intended to be a sort of "super assembler" - that is, the programmer could get very close to the metal without knowing the instruction set of the specific processor involved. Also, C programs could be ported from one hardware platform to another with a minimum of pain.
Examples of SyntacticAspartame (C/C++):
"Syntactic sugar causes cancer of the semicolon." -- AlanPerlis
SyntacticSugar in the right dosage can help as it makes idioms stand out more clearly, i.e. special language syntax for dealing with extensible arrays or hash tables. This is similar to the way indenting makes block structure stand out, even if the semantics of the language doesn't need it. Perhaps PythonLanguage and various other indentation sensitive languages excluded, or possibly not, as one could claim indentation-sensitivity is more sugary than begin/end markers.
Personally, my programming language preferences are similar to my preferences in meals. I like both to be tasteful, nourishing, and healthy. To me, that means a suitable dose of semantic carbohydrates to provide energy, some syntactic sugar to sweeten it a bit, a well-assorted library of proteins and fats, and a pleasant logical texture and composition. Salt and pepper to taste. Of course these ingredients can be mixed in all sorts of ways, and the result of course depends on the cook who prepares the meal. A language designed by a committee of course verifies the old saying about "too many cooks", and some swear to sugar-free diet languages, whereas others find they just don't taste right. Some languages combine very few ingredients in an astonishingly tasteful manner, whereas others seem to be made by taking what was available in the kitchen at the time and cooking it together into a strange stew. LanguageAsFoodMetaphor, anyone?

-- LasseHp
I've seen some good arguments for SyntacticSugar here, have you considered that it would be useful to create your own SyntacticSugar?

Have you pondered that a powerful macro feature should be a part of your programming language, that it should be possible to create constructs like "for" or "do/while" with the primitives of your language? Have you hit a brick wall with the syntax you've been able to cobble together using the C preprocessor?

Then you'd probably rather be using the macros of Scheme (DefineSyntax) or Lisp.

Or <bigwig>

Or in Java, JSE: http://jse.sourceforge.net/.

Am I the only person simultaneously terrified and slightly grossed out by the syntax of that JSE link? Holy moly, that's a maintenance nightmare waiting to happen. The reason Lisp gets away with macros is because of its minimal syntax. Java will probably be hurt more than it is helped if such a tool became part of common practice.
All programming languages are syntactic sugar for widely used patterns in previous generation languages. The structure of binary instructions became sugared as assembly mnemonics. Conventions for branching and iteration in assembly became flow control statements in third generation languages. Conventions for defining and calling subroutines in assembly became sugared as procedures in 3GLs. Conventions for organizing data in assembler became sugared as named variables, the stack of locals, the global segment, the dynamically allocated heap, arrays and structures. Conventions for implementing runtime polymorphism in C became virtual functions in C++. Hopefully, the industry will one day realize what LISP programmers have known all along, that programming is about creating languages in which we can express the solutions to problems, and we will start using languages that let us define our own syntactic sugar.

A'fuckin'men, the most logical statement on the page and the sad truth of the current state of the industry, why are so many of us shackled to languages we can't extend.

No. Ridiculous. Compiled languages are as far from syntactic sugar as a Cat backhoe is from a garden shovel. Use the tool appropriate for the job. Don't poke at a tool just because it doesn't fit your need.
Some languages, such as HaskellLanguage, define a base language; and then define a syntactic sugar on top of the base language. One of the first things a Haskell compiler does is desugaring - transforming the syntactic sugar into equivalent base code.

Macros in LISP and Scheme do the same thing: transform syntactic sugar into primitive code at 'read time'.

NemerleLanguage is similar - all the iteration constructs (c-style for loops, foreach, while, do...while, etc), for example, are defined as macros that transform the iteration into tail-recursive functions (and the conditionals are just macros layered over the pattern-matching syntax). And of course, you can write your own macros that can be used just as transparently as the ones from the standard library.
See: SyntacticSalt, BetterSyntacticSugar, ProgrammingLanguagesAreSyntacticSugar
Parallel: SyntacticSemtex
CategoryProgrammingLanguage

EditText of this page (last edited October 29, 2013) or FindPage with title or text search