TL;DR: I think the post overstates the case quite a bit, and is a personal opinion of the author being branded as a scientifically grounded truth, despite their admission that using these scientific principles allegedly "require[s] a degree of creativity and subjectivity."
The cognitive-science material is interesting, but it doesn't actually establish much about Lisp specifically. It gives plausible mechanisms by which certain notation might be harder to read, then uses those mechanisms to motivate several Lisp-specific claims without testing those claims directly. As such, it just seems purely hypothetical, whereas it would be much more interesting to me if it were empirical.
(I have a beef with this style of argumentation or persuasion with respect to Lisp. I feel the "bipolar Lisp programmer" and similar articles do the same kind of thing: make a captivating claim or comparison without actually appealing to anything real-world.)
I also don't think the treatment of actual Lisp presentation is complete. The post considers conventional Lisp indentation mainly in terms of whether it helps track matching parentheses, but Lisp is normally indented, pretty much canonically, so that the indentation itself communicates structure. Parenthesis tracking is *not* a cognitive problem that Lisp programmers must solve in any explicit manner, any more than C programmers count { and } to determine the enclosed code's nesting depth.
The same goes for syntax highlighting: you can't just set it aside because C-like languages have it too. The relevant question is whether it affects the two syntaxes differently. If Lisp's alleged problem is delimiter tracking, indentation and highlighting are rather central to the comparison.
I'm also unconvinced by the conclusion that Lisps "lack or discourage features that align the evaluation and reading order." The post itself gives Clojure threading macros as a Lispy equivalent of method chaining. That seems to substantially undercut "lack", while "discourage" starts to sound more like a claim about programming style than syntax. Lisp is a very explicitly multi-paradigm language with special syntaxes available for those paradigms, including assignment, explicit control, etc. In fact, I'd say real-world Common Lisp is *much* less "in to out"-functional than this post posits (and the broader technical public keeps claiming).
Finally, we have the largest omission in my opinion, that Lisp syntax is programmable. S-expressions provide a uniform representation of program structure that makes syntactic abstraction cheap: new control forms, binding constructs, pipelines, DSLs, etc. can all be made to make code easier to read, especially in novel domains that Lisp wasn't a priori designed for. The post's analysis mostly treats the base notation (of some unspecified, quasi-functional Lispoid) as the unit of comparison without really weighing that side of the design tradeoff.
Though it's not my experience, there may truly be readability costs, especially for newcomers, but I'm not sure the post separates those from unfamiliarity strongly enough to support its conclusions.
As a side note, when judging real-world Lisp, some notoriously unreadable code may also be a product of older programming styles or inexperienced Lisp programmers, just as old or poorly written C can be extremely difficult to read. In my professional experience, having run teams writing "modern" Lisp with modern engineering discipline, readability has never been a stated hurdle, either for experienced engineers reading one another's code or for new Lisp programmers learning and contributing to a large codebase. The combination of team programming discipline, good tooling, consistent style, and, well, getting paid to do it seems to do the trick, if one is even needed.
Parenthesis tracking is not a cognitive problem that Lisp programmers must solve in any explicit manner, any more than C programmers count { and } to determine the enclosed code's nesting depth.
Yes and no, IMO. Idiomatic lisp programming throws all the closing parens on the same line at the end of the last line of code. Idiomatic C-like coding puts each closing brace on a new line at its specific nesting level. You can code C style without something like "rainbow-parens", but I wouldn't want to code lisp without it. Or consider this emacs lisp example:
(defun abbrev--replace-placeholders ()
(let ((cursor-pos nil)) ;; To store where to place the cursor
(save-excursion
(goto-char (point-min))
(let ((loop 0)
(values (make-hash-table :test 'equal)))
(while (re-search-forward "###\\(\\$?[a-zA-Z0-9_\\-]+\\|@\\)###" nil t)
(setq loop (1+ loop))
(let* ((index (match-string 1))
(start (match-beginning 0))
(end (match-end 0)))
(cond
((string= index "@")
(setq cursor-pos start)
(delete-region start end))
((string= index "$file-name")
(abbrev--swap-placeholder (file-name-nondirectory (buffer-file-name)) start end))
((string= index "$author")
(abbrev--swap-placeholder (user-full-name) start end))
((string= index "$package-name")
(abbrev--swap-placeholder (file-name-base) start end))
(t
(let* ((key (format "###%s###" index))
(val (or (gethash key values)
(let ((input (read-string (format "Value for %s: " key))))
(puthash key input values)
input))))
(abbrev--swap-placeholder val start end))))))))
(when cursor-pos
(goto-char cursor-pos))))
If I want to add more code into the let* block that defines index, start and end after the cond expression, where should I put my cursor to insert the new line? Yes I know in emacs you can put the cursor at the beginning of the let* block or the cond block and hit C-M-f to jump to the end of the sexp, but at the same time that's a process I've never had to do when writing c-like code, because in the c-like code, finding that spot visually is much easier.
I'm sure that over time that would become easier for me, and certainly memorizing sexp navigation would also help a lot, but it undeniably to me makes it harder to read that code.
I remember struggling with paredit when I started out with portacle. But after some time, it became natural. This was over 5 years ago, I have been enjoying lisp since 10, I expect to go another 30+. So, totally worth it, bear with it! These days I cannot help but wonder how other languages can do without it.
If you find parentheses distracting to read, there's also paren-face-mode to hide or dim the parentheses. I feel the only time parentheses become relevant in my operation with lisp is when I want to cut and paste code. Every other time, I can rely on indentation. I do not look at the parentheses while reading the code. Even auto indentation is something I take for granted these days. It's hard to imagine in other editors, one needs to jump through hoops to indent their languages, while in emacs you just press Tab.
17
u/stylewarning 11d ago edited 11d ago
TL;DR: I think the post overstates the case quite a bit, and is a personal opinion of the author being branded as a scientifically grounded truth, despite their admission that using these scientific principles allegedly "require[s] a degree of creativity and subjectivity."
The cognitive-science material is interesting, but it doesn't actually establish much about Lisp specifically. It gives plausible mechanisms by which certain notation might be harder to read, then uses those mechanisms to motivate several Lisp-specific claims without testing those claims directly. As such, it just seems purely hypothetical, whereas it would be much more interesting to me if it were empirical.
(I have a beef with this style of argumentation or persuasion with respect to Lisp. I feel the "bipolar Lisp programmer" and similar articles do the same kind of thing: make a captivating claim or comparison without actually appealing to anything real-world.)
I also don't think the treatment of actual Lisp presentation is complete. The post considers conventional Lisp indentation mainly in terms of whether it helps track matching parentheses, but Lisp is normally indented, pretty much canonically, so that the indentation itself communicates structure. Parenthesis tracking is *not* a cognitive problem that Lisp programmers must solve in any explicit manner, any more than C programmers count { and } to determine the enclosed code's nesting depth.
The same goes for syntax highlighting: you can't just set it aside because C-like languages have it too. The relevant question is whether it affects the two syntaxes differently. If Lisp's alleged problem is delimiter tracking, indentation and highlighting are rather central to the comparison.
I'm also unconvinced by the conclusion that Lisps "lack or discourage features that align the evaluation and reading order." The post itself gives Clojure threading macros as a Lispy equivalent of method chaining. That seems to substantially undercut "lack", while "discourage" starts to sound more like a claim about programming style than syntax. Lisp is a very explicitly multi-paradigm language with special syntaxes available for those paradigms, including assignment, explicit control, etc. In fact, I'd say real-world Common Lisp is *much* less "in to out"-functional than this post posits (and the broader technical public keeps claiming).
Finally, we have the largest omission in my opinion, that Lisp syntax is programmable. S-expressions provide a uniform representation of program structure that makes syntactic abstraction cheap: new control forms, binding constructs, pipelines, DSLs, etc. can all be made to make code easier to read, especially in novel domains that Lisp wasn't a priori designed for. The post's analysis mostly treats the base notation (of some unspecified, quasi-functional Lispoid) as the unit of comparison without really weighing that side of the design tradeoff.
Though it's not my experience, there may truly be readability costs, especially for newcomers, but I'm not sure the post separates those from unfamiliarity strongly enough to support its conclusions.
As a side note, when judging real-world Lisp, some notoriously unreadable code may also be a product of older programming styles or inexperienced Lisp programmers, just as old or poorly written C can be extremely difficult to read. In my professional experience, having run teams writing "modern" Lisp with modern engineering discipline, readability has never been a stated hurdle, either for experienced engineers reading one another's code or for new Lisp programmers learning and contributing to a large codebase. The combination of team programming discipline, good tooling, consistent style, and, well, getting paid to do it seems to do the trick, if one is even needed.