These parentheses weren't decorative though,
they exposed the structure of the code, and they are a
minimal price to pay for extra clarity.
Well clarity is dependant upon the reader and, more specifically, how the reader reads.
My path to clarity is as follows: I first scan code at a high level, often referred to as speed reading[1] where I find having more parentheses simply gets in the way. The second is using fixation[2] where I stare at a small block of code. With both Arc and Clojure I have no trouble moving from scanning to fixation then to understanding (clarity). It could be that the author struggles with his/her reading method. Chances are the author learned with traditional L.I.S.P (Lots of Infuriatingly Stupid Parentheses) and therefore the newer lisp dialects are working against his/her read training. I however started with Arc & Clojure and I therefore experience the same lack of clarity when reading the traditional LISP dialects. To each their own.
Original blogger here. Apologies about the lack of indentation, I'm not sure how I missed that, it is a markdown conversion thing.
The point I was making in the blog is expressed more eloquently in [1], but to summarise: the difference between LISP and the countless languages that have risen and fallen during LISP's lifetime is that LISP directly represents the parse tree. By disposing of those parentheses in the (if ) statement, Arc has introduced the need to count the terms in the list to understand the sense of the code, in other words to parse it. Clearly the same is true of Python, C++, Haskell and many other languages I respect, but by placing a barrier between the code and the parse tree, Arc has abandoned the principle that makes LISP a global, rather than a local, minimum in the history of programming languages, and I think this is a mistake.
It sounds like what you like to see are s-expressions that fit these patterns:
homogeneous list of any number of X
fixed-length heterogeneous list of (X Y Z)
expression... which fits one of these patterns:
atom
call to X with args Y
Arc and Clojure make this more complicated by adding more cases, and I'll highlight Clojure's cases here:
map from X to Y
homogeneous vector of any number of X
vector alternating between X and Y, with no excess (like a map)
call to 'cond with args alternating between (expression) and
(expression), with no excess
call to 'case with args starting with (expression), followed by
alternations between (anything) and (expression), perhaps with
(expression) as excess
function body which might begin with a docstring and/or a metadata map
destructuring syntaxes
...
Between Arc and Clojure, I'm pretty sure Arc is intrinsically harder to auto-indent, because it doesn't distinguish between different cases using different kinds of brackets. Racket's a great example of what I mean; parens are used when the subsequent lines should be indented like function arguments, and square brackets are used otherwise.
For structured editing -- what you pursue -- we probably want even more static structure than what we want for auto-indentation.
I don't want to prod you to spend your time writing tools for niche languages or designing niche languages of your own, if that's not what you already want to do, but I'd like to ask what kinds of hypothetical languages you would like best....
Would you be eager to work with a lisp-like language where the AST has a few built-in notions of homogeneous lists, heterogeneous tuples, function calls, etc.? For instance, Lark defines an alternative to s-expressions that's more tailored to the ways the syntax is actually used (https://github.com/munificent/lark).
On the other hand, would you be eager to work with a language where the AST has an endless variety of possible cases, which can be extended by any programmer who wants to write an editor widget? Racket does something related to this, because it has an expressive pattern language for writing macros, and macros written this way generate good parse errors automatically (http://docs.racket-lang.org/syntax/Parsing_Syntax.html).
Personally, I've been kinda dreaming about both of these approaches to structured editing for a long time, but I'm still working on the run-time and link-time semantics of my language designs, so I've been unambitious when it comes to editing-time semantics. :)
Fair enough, you're not saying anything wrong here, but I still do not agree. This really this is about the trade offs each of us are willing to make.
i.e Programmatically[1] yes you might need to count terms, but for code readability I do not count the terms I let code indentation guide me.
I can certainly see how this code indentation factor may be seen as too free in form or structure to be appealing to many, but having less parentheses is a huge readability/enjoyability win. A win that, at least for me, leads to huge gains in productivity.
Also, you do have the option to pretend the token count is even:
(def example (x)
(if (is x 1) "One"
(is x 2) "Two"
'else "OOPS"))
It's up to you. In my mind power & flexibility are the big draws to LISP. If I wanted to be directed by the language as opposed to empowered by it I would just use C.
1. Once I've had to create a custom macro where I might have had to count the terms, but it's a rare event.
Welcome! I can see how lispers wouldn't like the arc approach, but I don't see how it makes arc more like non-lisps. What traditional language requires counting positions? I usually associate that with lisps.