Now the following from nomeata’s link is fascinating, but imo people should be cautious with syntactical changes:
Less parentheses 2: Whitespace precedence
The final proposal is the most daring. I am convinced that it improves readability and should be considered when creating a new language. As for Haskell, I am at the moment not proposing this as a language extension (but could be convinced to do so if there is enough positive feedback).
Consider this definition of append:
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs++ys)
Imagine you were explaining the last line to someone orally. How would you speak it? One common way to do so is to not read the parentheses out aloud, but rather speak parenthesised expression more quickly and add pauses otherwise.
We can do the same in syntax!
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
x:xs ++ ys = x : xs++ys
The rule is simple: A sequence of tokens without any space is implicitly parenthesised.
The reaction I got in Oxford was horror and disgust. And that is understandable – we are very used to ignore spacing when parsing expressions (unless it is indentation, of course. Then we are no longer horrified, as our non-Haskell colleagues are when they see our code).
But I am convinced that once you let the rule sink in, you will have no problem parsing such code with ease, and soon even with greater ease than the parenthesised version. It is a very natural thing to look at the general structure, identify “compact chunks of characters”, mentally group them, and then go and separately parse the internals of the chunks and how the chunks relate to each other. More natural than first scanning everything for (
and )
, matching them up, building a mental tree, and then digging deeper.
Incidentally, there was a non-programmer present during my presentation, and while she did not openly contradict the dismissive groan of the audience, I later learned that she found this variant quite obvious to understand and more easily to read than the parenthesised code.
Some FAQs about this:
-
What about an operator with space on one side but not on the other? I’d simply forbid that, and hence enforce readable code.
-
Do operator sections still require parenthesis? Yes, I’d say so.
- Does this overrule operator precedence? Yes!
a * b+c == a * (b+c)
.
-
What is a token? Good question, and I am not not decided. In particular: Is a parenthesised expression a single token? If so, then
(Succ a)+b * c
parses as ((Succ a)+b) * c
, otherwise it should probably simply be illegal.
-
Can we extend this so that one space binds tighter than two spaces, and so on? Yes we can, but really, we should not.
-
This is incompatible with Agda’s syntax! Indeed it is, and I really like Agda’s mixfix syntax. Can’t have everything.
-
Has this been done before? I have not seen it in any language, but Lewis Wall has blogged this idea before.
Well, let me know what you think!
Haskellers just seem to be Lisp programmers who hate parens (and love type systems, before you kill me).
Maybe if do bulleting (this is a better term than BlockArgument abuse) ends up being mainstream?
Also, with Unicode syntax, can bullets be a synonym for do?