All style guides seem to agree that in Lisp, all closing parenthesis should be put in the last line of code (instead of stacking theme line-by-line C style). However, if you do this, and then want to add more code after the last line, you either end up having to move cursor to correct location by counting parenthesis (usually augmented with editors' matching paren highlighting functionality); or just delete all the closing parens, add your code and add close all of 'em again. Both are tedious ways of writing code.
Looking around the internet, the "solution" I find is to edit the Lisp code structurally through editing in whole s-expressions. This seems yo imply that if I want to write Lisp without pulling out my hairs, I need to first learn a new way to edit code and only then go to actual programming; not to mention that always being stuck in the constraints of sexprs would inevitably be too..., well, constraining.
Is this true? Is learning Lisp should really be preceded with learning structured editing? And if so, how come no learning material or style-guide ever mention this practical hurdle?
I don't ever find myself counting parens.
Some people love Perl, some people hate it. Some people love C++, some people hate it. Some people love VS Code, some hate it. Etc etc.
Same thing with Lisp and the parentheses.
No language has perfect syntax, so I would say go with the language that irritates you the least.
(defun foo ()
(bar 1
(baz)))
Helpful for the developers are:* automatic parenthesis matching with highlighting matching pairs.
* colored parenthesis pairs
* syntax highlighting
* automatic indentation
* structural editing commands, up to rare editors which are structural only
If I would expect that I would often extend the function above by adding another function call, then I might write it as:
(defun foo ()
(bar 1
(baz))
)
and then add a call (defun foo ()
(bar 1
(baz))
(foo)
)
But that's rare and sometimes used in configuration files.Let's look at this:
(defun foo ()
(bar 1
(baz)))
Now we to add a new argument to the call to bar. What I would typically do is this:* put the cursor in front of one of the arguments. Here just (baz). The I would move over the s-expression to the end of the s-expression. A Lisp editor mode will have simple commands to move over s-expressions.
* the I would insert a newline and indent. A good Lisp editor will have a single command for that. The result is:
(defun foo ()
(bar 1
(baz)
))
The cursor will be in front of the )). Now we can enter the Lisp next form. (defun foo ()
(bar 1
(baz)
(hello)))
Now one can also think of this in terms of list manipulation: add a new form to the end of a form.The goal when you edit Lisp forms are:
* use the list structure as help to navigate in the form
* always keep the list structure properly indented and never do that manually, the editor has commands for that
* always keep the code compact
* don't format the code to make parentheses stand out. With more experience a Lisp developer will not use parentheses themselves a useful visual element. Learn to see whole expressions and not the isolated parenthesis as a visual token. It's a bit like learning a bike. Beginners think that they need to concentrate on keeping the bike stable. Later that's automatic.
* format the code such that indentation makes blocks visible (think of Python without parentheses for a similar example)
* learn the editor commands to move and edit list expressions
Lisp editors usually have a bunch of commands to work with s-expressions. Additionally there are specialized additions like 'paredit' and 'parinfer'. The latter infers parentheses from indentation.
Summary:
You don't need it when starting to learn to edit Lisp code, but over time it is useful to learn more about editing list expressions. Lisp code is made of list forms. Learn to make use of that as an advantage. The mental model of seeing code as simple list operations in the editor is actually relatively obvious and simple to learn.
Learn Lisp piece by piece. Incremental learning is aided by the tools.