I sure have a bit more problems maintaining Lisp code than writing it. But here I'm more comparing these two endeavors with one another while dealing with Lisp rather than comparing each one to the same endeavor in another language. Writing Lisp code is such a breeze that it is in fact unfair to compare other tasks to it. It's also a bit unfair to compare writing Lisp code to the task of writing code in many other languages.

It is very true that in syntax heavy languages, scanning is made very efficient from the syntax of the code. And sure enough, with big chunks of Lisp code, scanning is a chore. But it is important to understand that scanning is an enabler or, in a more mathematical expression, it is a sufficient condition to make scanning a palatable option. But it is absolutely not a necessary condition.

How?

Lisp code is generally terse and split into several tiny functions. There are some exceptions of course and, based on my experience, there is no exception for such exceptions: they are all tedious to read.

How tiny are the functions you may asked? Here's some stats about my project:

It has 8368 lines of Lisp code for a total of 676 definitions (variables, functions, macros and some other things). The average ratio of lines of code required per definitions is thus 12.37! That is completely, absolutely way way less than code in C, Java or Javascript. You may say that I just have a lot of very tiny utilities in the range of, say, 3 to 5 lines of codes. While it's true in a way, the overall average holds well to about 12 lines of code even if you look at the level of code systems (rather than the whole project) or even at the level of files (rather than whole libraries).

The point that I am trying to get across is that, while I agree there is a connection between having an idea of what the program is doing "at a glance" and gleaning information by scanning thanks to the syntax, this connection is certainly not forwarding any qualitative information about what a program is doing. I mean, from gleaning information from syntax to understand what a code does, nothing is passing that is remotely like 'this does that'. Syntax only guides your eyes. Scanning only allows to locate pieces of interest. But to know what a code does, you have to read it and there is no other way around.

And that's the very purpose of my essay. I am like you. I think I know better what a program is doing when I have some syntax but it's only an illusion. Syntax has absolutely no meaning in itself about what is being done. I have to read the name of the actions and what is passed to them. And if I want to really know what is being done, I have to read it all.

True, it's easier to read code with syntax guiding your eyes but when your code is only 12 lines, you can just read the whole very quickly and you know everything about it, not just the pieces you have gleaned. Syntax heavy languages make it easy to have a lot of information in a short amount of time but they make it more difficult to get the whole picture because they just spread code on so many lines with things less connected than in Lisp (two problems about that: statements do not return results and ask the programmer to do variable plumbing).

At the present time, I think it's all a matter of taste because getting to know what is happening still requires quite some work regardless of the language involved and the more complex what a program should perform, the more code there will be to read.

But Lisp has the edge here I think. Note that some of the various code systems I gave some stats about earlier are not trivial. One has two Lisp code parsers (one of them just gives the stats I exposed, the other one identifies dependencies): 1194 lines for 86 definitions thus a ratio of 13.88. Another one "full view debugs" code: 659 lines for 39 definitions thus a ratio of 16.9.

Despite the goals these code systems tackle, they do not sky-rocket in their stats; every one of them stays very reasonable. And both projects bring much insights about the structure of the code and what is being done. Especially the latter. Full view debugging is about computing all intermediate results inside a given code and layout them all in the browser. It's like when one debugs by hand except that it is all done automatically and everything is here for you to see.

In other words, you can scan and you do not get an idea of what the program is doing. You get what it is really doing. And because Lisp syntax is simple, that full view debugger works on any Lisp code (although of some of the most exotic actions, it does not go into them).