‹ BackHN Continuity

Thread

What makes Lisp difficult to read?

47 points · 81 comments · ibobev

  1. whartung · · focus · HN ↗
    The parentheses are large glyphs that distract the eye, and do not stand out (to the untrained eye) as delimiters.

    Consider:

      (defun split-line (line)
        (remove-if #'(lambda (word) (string= word ""))
                   (split-sequence:split-sequence #\Space line)))
    
    Now imagine if we had some "lower weight" glyph besides the paren.

      .defun split-line .line,
        .remove-if #'.lambda .word, .string= word "",,
                   .split-sequence:split-sequence #\Space line,,,
    
    Obviously a contrived example replacing () with ., but you can see how "heavy" the parens and how they can dominate what the eye sees.

    With experience, the parens vanish. The parens being large and common take control of the conversation more than they should.

    1. waffletower · · focus · HN ↗
      OMG, the "improved" example is so cluttered and far far far less readable -- and even foreign -- to someone like me that has developed using lisp professionally for at least 10 years.
      1. regenschutz · · focus · HN ↗
        That's a crazy effect. For me, as someone who has a very minimal understanding of Lisp (apart from messing with it in Emacs for at most an hour), the improved version is much more readable.
        1. WillPostForFood · · focus · HN ↗
          Do you mean readable, as in it is easier for you to match "." to "," than ( to ), or is it just easier to look at without reading because there is less there.
          1. regenschutz · · focus · HN ↗
            The latter. Maybe it's different in Lisp, but whenever I read code, I rarely care about the exact order of operations, just which ones are actually being executed. In that regard, the improved version allowed me to comprehend the gist of what was happening much faster than the regular version did. For a few seconds, before even attempting to start comprehending the actual operations being executed, my eyes were stuck trying to comprehend the parentheses.
    2. acomjean · · focus · HN ↗
      Lisp is why I started using emacs and its parens matching features.
    3. whalesalad · · focus · HN ↗
      I don't think the parens are the issue.

      But when your function ends with ))))))))) -- that is the issue. Too much shit is being shoved into one method. But this is not the fault of lisp, it's the fault of the programmer who is wielding it.

      1. kccqzy · · focus · HN ↗
        That is frankly not a problem at all. People rarely bat an eye when your Python function ends by having eight simultaneous levels of dedent. People definitely don’t bat an eye when your HTML ends with </span></span></div></div></td></tr></table></section></body></html>. All you need is just good indentation, which is enforced in Python but optional in Lisps; then lazy programmers take shortcuts and don’t indent at all.
        1. whalesalad · · focus · HN ↗
          We can agree to disagree
    4. Avshalom · · focus · HN ↗
      this actually gets at the real problem. Lisps are wordy as hell. like jesus

        (split-sequence:split-sequence #\Space line)
      
      now imagine if that was

        (split-string " " line)
      
      image if the whole function was

        (defun split (line)
          (remove [\(word) (= "" word)] [split-string " " line]))
      
      or even

        (defun split (line)
          (remove "" [split-string " " line]))
      
      
      *using [] in place of rainbow parens for clarity of sub arguments
      1. Jtsummers · · focus · HN ↗

          (split-sequence:split-sequence #\Space line)
        
        Why would you do that? You could just use `uiop:split-string` and import the function symbol into your current namespace so you can call it as `split-string`.

          (split-string "a b c")
        1. Avshalom · · focus · HN ↗
          I mean ask OP, I don't know what's what in the Scheme rXrs or Common Lisp standard libraries.

          Although my general stance remains, most lisp code bases I've seen are remarkably verbose which leads to a glazing over far more than the lack of distinct symbols or prefix notation

      2. fweimer · · focus · HN ↗
        I think with CLOS, you can go back to using single verbs for function names. However, this has a performance cost. Encoding the receiver type in the function names makes the call much easier to optimize.

        What remains is field access. Curiously, first-edition K&R C actually required similar type-encoding in field names because field names were global:

        <a href="https:&#x2F;&#x2F;usenet.trashworldnews.com&#x2F;?thread=288637" rel="nofollow">https:&#x2F;&#x2F;usenet.trashworldnews.com&#x2F;?thread=288637

        Same for ML, which is roughly of the same age, except that it took much longer for ML-derived languages to lift this restriction.

        On the other hand, every time I wrote down examples that I think should look really bad in prefix notation, like this one:

            p3.x := (p1.x + p2.x) &#x2F; 2;
        
        It is actually not so terrible with a sufficiently streamlined prefix syntax:

            (setf x p3 (&#x2F; (+ (. x p1) (. x p2)) 2))
        
        But maybe there should be a mechanism that the reader transforms p1.x to (. x p1), in the same way that it transforms &#x27;s into (quote s). Then we get this:

            (setf x p3 (&#x2F; (+ p1.x p2.x 2)))
        
        Or if there is a concept of a place:

            (set p3.x (&#x2F; (+ p1.x p2.x 2)))
        
        But that probably needs static typing for an efficient implementation (or set needs to deconstruct its first argument during compilation).
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.