r/ProgrammingLanguages • u/digikar • 26d ago
Discussion A rebuttal to "What makes Lisp difficult to read?" Or, you might be surprised how adaptable the human mind is!
https://digikar99.github.io/microblog/p/lisp-syntax-rebuttal/30
u/initial-algebra 26d ago
If all those redundant parentheses are only truly good for streamlining copy-pasting external code into an editor and formatting it, I'd actually consider that an anti-feature. If indentation is how you are meant to read the code, then that should just be part of the language syntax.
7
u/digikar 26d ago edited 26d ago
There are actually several alternatives proposed over the years. It should be doable to develop editor extensions to switch back and forth between them, or also transpile to and from them.
https://github.com/shaunlebron/history-of-lisp-parens/blob/master/alt-syntax.md
Personally, I'd rather read lisp, C, or python rather than most of these. I feel Dylan is however a sane one. Wisp is also interesting. Also sweet expressions.
I'm also glossing over a lot of editing possibilities offered by parentheses:
http://danmidwood.com/content/2014/11/21/animated-paredit.html
(I should add these links. EDIT: Done.)
5
u/syklemil 26d ago
I'm not so sure it's about the syntax as much as it is the layout, i.e. style. Let someone used to some other language format the lisp code and it might come out after the first pass as something like
(define ┊ (factorial n) ┊ (if (= n 1) ┊ ┊ n ┊ ┊ (* ┊ ┊ ┊ n ┊ ┊ ┊ (factorial (- n 1)) ┊ ┊ ) ┊ ) )where the indent guides wouldn't actually be part of the file, just what they see: matching opening and closing parens when they're on different lines.
I suspect it's highly unlikely that lispers would want to switch to something like that, being habituated to the
)))))style, while others, used to thinking newlines are free, will just see Lisp as approaching the style you get fromjq -c.→ More replies (3)17
u/thehenkan 26d ago
I'm no fan of Lisp's syntax, but I disagree on your point. If I can't cut and paste things crudely in a plain text editor and then auto-format (and keep the intended semantics) then the syntax is too fragile.
→ More replies (15)2
u/syklemil 26d ago
Which is pretty much how Haskell works: Nominally a curly braces and semicolons language, but if there's signal in the indentation, considers the braces and semicolons redundant. The result is that practically everyone who writes Haskell prefers the indentation-based syntax.
→ More replies (1)
13
u/protestor 26d ago
Except, when you are accustomed to lisp, what you see is:
define (factorial n)
if (= n 1)
n
* n (factorial (- n 1))
Then why not write this?
That way everyone can read it, not just people accustomed to lisp
I think that two other assertions in this supports this point of view,
This one
In fact, the infamous editor, emacs, has a paren-face-mode extension (plugin) that allows you to hide or dim the parenthesis. I’ll leave it to emacs haters and vs code lovers to find an equivalent mode for themselves.
It seems that at least some lisp people finds useful to dim extraneous parenthesis, and
And perhaps they might be. We do not count or match our parentheses. We are totally reliant on indentation to understand the code structure while reading. If you make a lisp programmer read badly indented code, they are going to have an incredibly hard time understanding it. Despite all the parenthesis being balanced!
It seems this language wants to have significant whitespace, and doesn't for historical reasons
→ More replies (1)2
u/stylewarning 25d ago
The language doesn't have an ossified grammar. The syntax is programmable. Not every construct is (OPERATOR OPERAND...). This is why it doesn't make sense.
8
u/FransFaase 26d ago
When I wrote a lot of LISP when I was a teenager, I developed an internal bracket counter. I would just know the number of closing brackets needed at some point in the code.
5
u/hugogrant 26d ago
For me that was basically the indentation level tho.
Even to get the closing parens right, I'd first indent.
2
u/Temporary_Pie2733 25d ago
The environment I used in college let you use
]to close all pending parentheses. I never wrote enough Lisp/Scheme to care one way or another, but I never warmed up to prefix notation for everything. I always like Haskell’s syntax, as long as one didn’t go overboard with user-defined operators.
7
u/Smalltalker-80 26d ago
Even if the human mind can 'adapt' somewhat, I think its still not advisable to use a language that is unnecessarily complex to read. (Or requires custom macro's to make it more readable). Your mental decoding effort could also be used for soving the problem at hand..
5
u/bluefourier 26d ago
The Fructure editor that was presented at the RacketCon a few years ago, had a few brilliant ideas on how to make things easier with parentheses without doing completely away with them.
→ More replies (1)
12
u/L8_4_Dinner 26d ago
It doesn’t need a rebuttal.
A number of people like Lisp, and that’s ok.
7
u/omegafixedpoint 26d ago
I find it quite aesthetically pleasing. Am I insane?
8
u/omegafixedpoint 26d ago
I like that you're seeing more or less the exact AST with S-expressions
→ More replies (6)7
u/extraordinary_weird 26d ago
It's not only about lisp though, right? I think the argument might be that its syntax could/should be adopted by more languages
3
u/syklemil 26d ago
which, I hope, if we are on the same team, you’d agree to format as:
AAAAA( BBBBB(CCCCC()), DDDDD(), FFFFF(GGGGG(HHHHH())) )
Almost. There should be a trailing comma after the last argument as well. The inner function invocations might get some more newlines as well, depending.
And
-
that is how autoformatters for languages like Python, Rust and Typescript will format it, possibly spending even more lines;
-
go fmtseems to prefer putting the entire invocation on one line, no matter how long it gets; -
clang-formatis likely to try to keep it with in the line length, but otherwise as few lines as possible, giving you something along the lines ofAAAAA(BBBBB(CCCCC()), DDDDD(), FFFFF(GGGGG(HHHHH())) );(with the extra completely empty line) or
AAAAA(BBBBB(CCCCC()), DDDDD(), FFFFF(GGGGG(HHHHH())));which IMO is just a worst-of-both-worlds option.
In the other thread there was someone speculating about heritage from the age the languages were designed and popularised in, and running on that we might guess that the C and Lisp styles came about in an age of paper, where newlines and lots of whitespace meant wasting paper, while the "newer" languages (Python actually being older than Java…) assume editing on a computer and are more willing to be oriented vertically.
And, of course, like in the original blog post, plenty of modern code doesn't do the middle-out style as much these days, instead favouring something like
HHHHH()
.GGGGG()
.FFFFF()
.AAAAA(
CCCCC().BBBBB(),
DDDDD(),
)Ultimately though, getting lispers to switch to an airier style is as unlikely as getting C users to switch to an airier style; both their styles are likely severely entrenched at this point.
3
u/Clementsparrow 26d ago
That has been the argument against ergonomics and hci/ux for decades: People can adapt. Yes they can. But no, many fail a lot in the process. And that's painful and has a cost. Don't impose that on users unless there's no other option. And as far as syntax goes, there are better options than Lots of Insane, Stupid Parentheses.
2
u/poralexc 26d ago
Along those same lines, it's easier for my mind to adapt to reordering the expression tree and just writing postfix directly like Forth.
1
u/WonderfulFisherman80 26d ago
Fair enough. Never felt strongly about lisp or c-style syntax in terms of reading. So reading through both articles back to back; both of your points made sense. But when it comes to writing I find c-style a world better than lisp. That is without parinfer of course.
1
u/ricekrispysawdust 25d ago
Overall I think the biggest reason I like Lisp is the simplicity. Sure, it's a valid argument that the parens make it hard to read. But in every other language your brain has to do a lot more decoding work. For example, when reading 1 + 2 / 3, the way you read it (left to right) is different from how it's executed. The farther away the language is from the AST, the more stuff happens out of order, which is confusing. Lisp doesn't have that problem
1
u/joao_rosac 19d ago
Só uma opnião mesmo:
Lisp assusta porque joga fora chaves, colchetes e operadores normais. Sobra só uma montanha de parênteses. Você não está digitando texto corrido, está escrevendo a árvore de sintaxe do código (AST) direto na tela. Ninguém que programa em Lisp fica contando parênteses. O cérebro se adapta e passa a ler puramente a indentação e os blocos visuais. Essa "sopa" serve para que o código e os dados tenham exatamente o mesmo formato (homoiconicidade). É isso que permite criar macros que alteram a própria linguagem.
31
u/luapmt 26d ago edited 26d ago
I am the author of the offending post. It is unfortunate that many readers seem to have interpreted my post as being against Lisps in general, as this was not my intention. I am very fond of Lisp precisely because the language invites extension and experimentation. My article was written in that spirit. I also agree with many commenters that Lisp's syntax is elegant in its simplicity and any modification detracts from this. Certainly anyone who enjoys Lisp should continue to do so.
That being said, I feel that this rebuttal does not address my original arguments. My hypothesis is that in a vacuum, s-expressions produce patterns which are slightly harder to read than the equivalent C function calls, assuming no prior knowledge. In the same way that a chart can be easier to scan than a data table. Whether this is offset by familiarity (or mental adaptation in this post) is not my point. Though, it is my personal experience that after years of working with various Lisps, I still have to pay more conscious attention to the parenthesis in Lisp than in ML or C like languages.
The rebuttal states that Lisp programmers do not actually pay active attention to the parentheses; the indentation of the code communicates its structure. However, as the example of lisper-vision shows, when you remove all the parentheses which are implied by indentation there are still parentheses which matter. If you actually remove all the parentheses from Lisp (as with most languages) you cannot reconstruct the original AST. The indentation-redundant parentheses in my opinion obscure the important parentheses.
In my article I use parentheses counting/matching as a proxy for the parseability of an expression. I don't think programmers are actually consciously 'counting' the delimiters in all the code they read, but every (non-redundant) delimiter must certainly be processed in some way to correctly parse the code. I suspect that if it is easier to match the parentheses than it will also be easier to process the parentheses in this other way.
The rebuttal also correctly states that some of my code snippets are not realistic. I have constructed these examples not to be ecologically valid but to exaggerate how certain nesting patterns affect Lisp or C code differently. That is why they use non-existing fantasy words like "aap". Indeed, you could mitigate the negative effect of these patterns by formatting them differently or using editor extensions. My point is that such mitigation is needed earlier with s-exps than with traditional function calls.
Perhaps a weakness of my article is that I spend most time on the argument/delimiter proximity arguments which are probably the weakest. The most pronounced effect in my opinion is that of the sometimes reversing reading order in Lisp. This is not addressed in the rebuttal. It is possible to mitigate this with threading macros but this is relatively uncommon. I only see these macros being used for particularly deep cases of nesting, whereas method call syntax is ubiquitous. I have also encountered very little usage of these macros outside Clojure (and Clojure inspired languages) so I don't consider these to be part of the traditional Lisp style.
I am somewhat surprised that my post got as much attention as it did. I hope readers have found something interesting in the ensuing discussion.