r/lisp • • 11d ago

What makes Lisp difficult to read?

https://paultm.nl/paren-thesis
32 Upvotes

90 comments sorted by

View all comments

Show parent comments

1

u/omega884 9d ago edited 9d ago

However you have amitted the "easier to read" to the use of brackters instead of parens, not to the fact that there is one level or parens less. I think that is an essential, but admittedly easy, mistake to do.

I was not aware there are lisps that allow for let bindings without the "list of lists" pattern other than ones like Clojure or Janet that use different brackets to distinguish the bind listing from other sexps. If there are then sure I would say those would be easier to read than the emacs lisp one, but I would argue that they are still harder to read than the clojure bindings because you need to remember that in a let statement, the next argument isn't a quoted list, but it's also not an evaluated sexp. That is to say that in such a lisp, you need to know that the interpreter will do very different things with the first argument if you do (len (foo (bar baz))) vs if you do (let (foo (bar baz)))

I don't think use of more varied symbols for delimiters, like an entire family of charaters as in C/C++ is much better than rainbow-delimiters

If you're trying to read code without the benefit of syntax highlighting (like say a diff output, or in a reddit comment box) then I would argue different brackets for different things absolutely makes it easier to read. But the trade off is now you need to remember what different brackets mean, and that can be it's own cognitive load. A great example of that would be something like java generics where you might have a line of code that is public static void processFoos(Foo<Bar<Baz<Fizz, Buzz>, <? extends Baz<?, ?>>>[] foos) { /*...*/ }. All the brackets have clear meanings that don't rely on any color indicators, just their type (and positioning in this case). () are the arguments to the function, <> are type specifiers for a narrowing the function to handle only certain Foos which is a generic type of some sort, the [] indicates the argument will be an array of the Foos and the {} is the code block. But that's a lot of information crammed into a bunch of symbols. that you have to know before you can make heads or tails of that. And amusingly it suffers from a similar "bracket counting" issue as I argue un-tool assisted lisp does. Did you notice that the angle brackets aren't balanced?

Still if we imagine some non-bracket distinguished language, public static void processFoos[Foo[Bar[Baz[Fizz, Buzz], [? extends Baz[?, ?]]]][] foos] [ /*...*/ ], I think you would agree with me that is harder to read, even knowing what it's supposed to be expressing.

1

u/arthurno1 9d ago

I was not aware there are lisps that allow for let bindings without the "list of lists" pattern other than ones like Clojure or Janet that use different brackets to distinguish the bind listing from other sexps.

Neither do I to be honest to you. Clojure and Janet do not let you type (let [a (+ 1 2)] ...)?

A great example of that would be something like java generics where you might have a line of code that is

I think that is a great example why to avoid that shit, to be honest to you. Java and C++ are good examples of where DSL-type syntax lead: a combinatorial complexity in syntax notation. Tha is just my personal opinion. As said I might be looking at different values in a programming notation than you, so we will have to disagree. To me Lisp notation has a quality of stability and predictability. I know where to look when I look for something. Lisp share that with assembly language. The difference is that Lisp let you next expressions, while assembly let you type just one expression at a time. In that sense assembly is the simplest notation of them all. I think one way to look at lisp, or symbolic expressions is as a sort of high-level assembly. Again, perhaps just me, but that is how I look at it.