Notes on syntax


The last few years the expressiveness of programming languages have been on my mind. There are many things that comes into consideration for expressiveness, not matter what definition you actually end up using. However, what I’ve been thinking about lately is syntax. There’s a lot of talk about syntax and many opinions. What made me start thinking more about it lately was a few blog posts I read that kind of annoyed me a bit. So I thought it was time to put out some of my thoughts on syntax here.

I guess the first question to answer is whether syntax matters for a programming language. The traditional computer science view is largely that syntax doesn’t matter. And in a reductionist, system level view of the world this is understandable. However, you also have the opposite view which comes strongly into effect especially when talking about learning a new language, but also for reading existing code. At that point many people are of the opinion that syntax is extremely important.

The way I approach the question is based on programming language design. What can I do when designing a language to make it more expressive for as many users as possible. To me, syntax plays a big part in this. I am not saying that a language should designed with a focus on syntax or even with syntax first. But the language syntax is the user interface for a programmer, and as such there are many aspects of the syntax that should help a programmer. Help them with what? Well, understanding for one. Reading. Communicating. I suspect that writing is not something we’re very much interested in optimizing for in syntax, but that’s OK. Typing fewer characters doesn’t actually optimize for writing either – the intuition behind that statement is quite easy: imagine you had to write a book. However, instead of writing it in English, you just wrote the gzipped version of the book directly. You would definitely have to type much less – but would that in any way help you write the book? No, probably it would make it harder. So typing I definitely don’t want to optimize. However, I would like to make it easy for a programmer to express an idea as consicely as they can. To me, this is about mentioning all things that are relevant, without mentioning irrelevant things. But incidentally, a syntax with that property is probably going to be easier to communicate with, and also to read, so I don’t think focusing on writing at all is the right thing to do.

Fundamentally, programming is about building abstractions. We are putting together extremely intricate mind castles and then try to express them in such a way that our computers will realize them. Concepts, abstractions – and manipulating and communicating them – are the pieces underlying programming languages, and it’s really what all languages must do in some way. A syntax that makes it easier to think about hard abstractions is a syntax that will make it easier to write good and robust programs. If we talk about the Sapir-Whorf hypothesis and linguistic relativity, I suspect that programmers have an easier time reasoning about a problem if their language choice makes those abstractions clearer. And syntax is one way of making that process easier. Simply put, the things we manipulate with programming languages are hard to think about, and good syntax can improve that.

Seeing as we are talking about reading – who is this person reading? It makes a huge difference if we’re trying to design something that should be easy to read for a novice or we’re trying to design a syntax that makes it easier for an expert to understand what’s going on. Optimally we would like to have both, I guess, but that doesn’t seem very realistic. The things that make syntax useful to an expert are different than what makes it easy to read for a novice.

At this point I need to make a request – Rich Hickey gave a talk at Strange Loop a few months ago. It’s called Simple made Easy and you can watch it here: http://www.infoq.com/presentations/Simple-Made-Easy – you should watch it now.

Simply put, if you had never learnt any German, should you really expect to be able to read it? Is it such a huge problem that someone who has never studied Prolog will have no idea what’s going on until they study it a bit? Doesn’t it make sense that people who understand German can express all the things they need to say in that language? Even worse, when it comes to programming languages, people expect them to be readable to people who have never programmed before! Why in world would that ever be a useful goal? It would be like saying German is not readable (and is thus a bad language) because dolphins can’t read it.

A tangential aspect to the simple versus easy of programming languages is also how our current syntactic choices echo what’s been done earlier. It’s quite uncommon with a syntax design that becomes wildly successful while looking completely different from previous languages. This seems to have more to do with how easy a language is to learn, rather than how good the syntax actually is by itself. As such, it’s suspect. Historical accidents seem to contribute much more syntax design than I am comfortable with.

Summarizing: when we talk about reading programming languages, it doesn’t make much sense to optimize for someone who doesn’t know the language. In fact, we need to take as a given that a person knows a programming language. Then we can start talking about what aspects reduce complexity and improve communication for a programmer.

When are talking about reading of languages, one thing that sometimes come up is the need for redundancy. Specifically, one of the blogs that inspired these thoughts basically claimed that the redundancy in the design of Java was a good thing, because it improved readability. Now, I find this quite interesting – I have never seen any research that explains why this would be the case. In fact, the only argument in support I’ve heard that backs up the idea is that natural languages have highly redundant elements, and thus programming languages should too. First, that’s not actually true for all natural languages – but we must also consider _why_ natural languages have so much redundancy built in. Natural languages are not designed (with a few exceptions) – they grow to have the features they have because they are useful. But reading, writing, speaking and listening of natural languages have so different evolutionary pressures from each other that they should be treated differently. The reason we need redundancy is simply because it’s very hard to speak and listen without it. For all intents and purposes, what is considered good and idiomatic in spoken language is very different from written language. I just don’t buy this argument for redundancy. It might be good with redundancy in programming language syntax, but so far I remain to be convinced.

It is sometimes educational to look at mathematical notation. However, mathematical notation is just that – notation. I’m not convinced we can have one single notation for programming languages, and I don’t think it’s something to aspire to. But the useful lesson from math notation is how terse it is. However, you still need to spend a long time to digest what it means. That’s because the ideas are deep. The thinking that went into them is deep. If we ever come to a point where programming languages can embody as deep ideas in as terse a notation, I suspect we will have figured out how to design programming language syntax that is way better than what we have right now.

I think this covers most of the things I wanted to cover. At some point I would like to talk about why I think Smalltalk, Ruby, Lisp and some others have quite good syntax, and how that syntax is intimately related with why those languages are powerful and expressive. Some other random thoughts I wanted to cover was evolvability of language syntax, whether a syntax should be designed to be easy to parse, and possibly also how much English specifically has impact the design of programming languages. But these are thoughts for another time. Suffice to say, syntax matters.


15 Comments, Comment or Ping

  1. Andreas

    “I’m not convinced we can have one single notation for programming languages” yes I think in fact it makes much more sense to model the programming language your working with according to a limited subsystem.

    What are your thoughts on Nile?

    https://github.com/damelang/nile

    Which syntax seems to be heavily inspired by some math notation.

    regards Andreas

    February 12th, 2012

  2. If you want to see a really nice syntax design, take a look at Oz http://en.wikipedia.org/wiki/Oz_%28programming_language%29.

    Each semantic concept pretty much has its own syntactic representation, which helps to clarify and make consistent the meaning of code.

    This is sort of the opposite of Lisp, where everything looks like a list syntactically.

    February 12th, 2012

  3. “Programs must be written for people to read, and only incidentally for machines to execute.”
    – Abelson & Sussman, Structure and Interpretation of Computer Programs

    by extension that means the syntax of a language should at the very least not prohibit such a relationship between the author and the reader.

    February 12th, 2012

  4. No One

    Take a look at the K programming language (and its open source implementation, Kona).

    When written idiomatically, it looks like line noise, but when you are familiar with it (unlike german), you notice that the brevity makes a qualitative difference.

    E.g., to compute an average of a list x, you use (+/x)%#x – pronounced “(sum over x) divided by count of x”. It’s shorter than wrting “average x” (if you have average in your library), and a lot shorter than “Math.average(x)”. You use full expressions, so you don’t actually have to consult the manual to see what “average” does on null vectors, infinites, or NaNs — it’s all there. That’s a qualitative difference.

    Additionally, to efficiently solve maximum-subsequence-sum on a list x, you do |/(0|+)\x — but you’ll have to learn a little more K for that to make sense. Trust me, though — the terseness here makes a qualitative difference to the kind of solutions people use.

    February 13th, 2012

  5. I wanted to note that mathematical notation has always been a source of controversy in itself, because it too came from a historical process rather than first principles and therefore is as full of unnecessary twists, overloading, and ambiguity as anything else. For example, the notations for functions, derivatives, integrals are terribly broken. One could argue that higher mathematics would be much more accessible if the notation were not so broken, and many mathematicians look toward computer languages for an inspiration for a better notation. A concrete example of using an unorthodox mathematical notation, to better express physics, is http://mitpress.mit.edu/sicm/

    February 13th, 2012

  6. @ola: Good thoughts, and thanks for pointing out “Simple made Easy” – everyone should see that.

    @no one: Speaking of K… it’s basically a plain-ASCII version of APL. Why should syntax be limited to ASCII? Using an extra modifier key, we get 48 extra symbols; APL uses about 20 of them. I’ve tried it. It’s a bit harder to type, but easier to read (once you warm up to the idea of a completely different syntax).

    @franklin chen: Math notation is a mess indeed. APL was an attempt to unify it, influenced by Einstein’s, Heaviside’s, and a few other’s notation conventions. “Conventions” sums it up pretty well… there’s no perfect notation; people adapt it to their domain for convenience. That’s a little harder to do with programming languages… but sometimes it’s worth the effort and the incompatibility…

    February 13th, 2012

  7. grover

    @TOM NOVELLI

    > Speaking of K… it’s basically a plain-ASCII version of APL. Why should syntax be limited to ASCII? Using an extra modifier key, we get 48 extra symbols; APL uses about 20 of them. I’ve tried it. It’s a bit harder to type, but easier to read (once you warm up to the idea of a completely different syntax).

    APL only adds a few extra symbols to Ascii but what about all of Unicode, both symbols and foreign language alphabets?

    @ola

    > I suspect that writing is not something we’re very much interested in optimizing for in syntax, but that’s OK. Typing fewer characters doesn’t actually optimize for writing either – the intuition behind that statement is quite easy: imagine you had to write a book. However, instead of writing it in English, you just wrote the gzipped version of the book directly. You would definitely have to type much less – but would that in any way help you write the book? No, probably it would make it harder. So typing I definitely don’t want to optimize.

    You say writing is not something you’d optimize for in syntax, giving the example of how many characters to type. But what if you want to type in more than just Ascii characters, perhaps all Unicode characters. Being able to enter them all easily is the real issue I think. Wouldn’t you like code that uses ≤ instead of =, ∧ for &&, ∨ for ||, ∈ for ‘in’, ∅ for ‘null’, or some more of these (just a small selection of Unicode 6.1’s 110,000 tokens)…

    ∀∃∁∂∆∇∊∋∍∎∏∐∑∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∥∩∪
    ∫∮∱∲∳∴∵∶∷∸∹∺∻∼∽∾∿≀≂≃≅≆≈≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟
    ≡≣≦≧≨≩≪≫≬≲≳≶≷≺≻≼≽≾≿⊂⊃⊆⊇⊊⊋⊌⊍⊎⊏⊐⊑⊒⊓⊔
    ⊕⊖⊗⊘⊙⊚⊛⊜⊝⊞⊟⊠⊡⊢⊣⊤⊥⊦⊧⊨⊩⊪⊫⊰⊱⊲⊳⊴⊵⊶⊷⊸⊹⊺⊻⊼⊽⊾
    ⊿⋀⋁⋂⋃⋄⋅⋆⋇⋈⋉⋊⋋⋌⋍⋎⋏⋐⋑⋒⋓⋔⋕⋖⋗⋘⋙⋚⋛⋜⋝⋞⋟⋤⋥⋦⋧⋨⋩
    ⋮⋯⋰⋱

    February 13th, 2012

  8. All notation comes from removing duplication: I write something often, so I want a shorthand for it.

    February 14th, 2012

  9. Michael Feathers

    I generally agree with your blog, but thing that I’m not sure about is whether languages should be optimized for readability over writability. I think that when things are going well in a language, it’s a false dichotomy.

    There’s research out there that indicates that “conciseness is better” when it comes to syntactic elements: http://www.scala-lang.org/node/3069

    It seems to me that if we believe that concise is better, ease in reading and writing and aren’t at odds except in the case where very concise constructs can be mistaken for each other. I don’t know enough J or K to know if experienced readers have that problem with them, but it does to me that if that problem is tractable, we’re headed toward the APL-ish, J-ish, K-ish languages.

    February 16th, 2012

  10. I don’t know if APL has much of a chance. Popular C-family languages (Javascript, Python, Ruby, etc) also have concise visual symbols. I guess the APL family’s advantage is having symbols for functional operations.

    Classic APL lacks modern control structuers and isn’t suitable for things like imperative loops. I had an idea to embed APL expressions in Lisp to provide control structures… actually started a little prototype implementation; should put it on Github…

    February 24th, 2012

Reply to “Notes on syntax”