• lihaoyi 3 days ago

    This post misses the IMO best indentation scheme for lisp, which I used for my college class where we had to use MIT scheme:

        (define (match:element variable restrictions)
            (define (ok? datum)
                (every 
                    (lambda (restriction)
                        (restriction datum)
                    )
                    restrictions
                )
            )
            (define (element-match data dictionary succeed)
                (and 
                    (ok? data)
                    (let ((vcell (match:lookup variable dictionary)))
                        (if vcell
                            (and 
                                (equal? (match:value vcell) data)
                                (succeed dictionary)
                            )
                            (succeed (match:bind variable data dictionary))
                        )
                    )
                )
            )
            element-match
        )
    
    It may not be densest or most compact indentation scheme, but damn is it readable for someone without a lisp/scheme background!
    • davvid 3 days ago

      > This post misses the IMO best indentation scheme for lisp [...]

      Likewise, a lispier(?) and more compact compromise?:

          (define (match:element variable restrictions)
              (define (ok? datum)
                  (every 
                      (lambda (restriction)
                          (restriction datum))
                      restrictions))
              (define (element-match data dictionary succeed)
                  (and 
                      (ok? data)
                      (let ((vcell (match:lookup variable dictionary)))
                          (if vcell
                              (and 
                                  (equal? (match:value vcell) data)
                                  (succeed dictionary))
                              (succeed (match:bind variable data dictionary))))))
              element-match)
      • nine_k 2 days ago

        It becomes much harder to notice if you have closed all the right matching parens, and hence where a token after the closing paren belongs. When the closing paren is exactly below the opening paren, on the same column, it becomes much easier to see the structure. It's a very good thing for students who just learn Lisp.

        • ludston 2 days ago

          But all the cool kids are using paredit or parinfer which means you don't actually ever write the closing parens yourself.

          Counting parens is silly when the editor can do it for you.

          • davvid 2 days ago

            Likewise, it's better to optimize for experienced readers than it is to optimize for students.

            • harperlee 2 days ago

              Some time ago parinfer (https://news.ycombinator.com/item?id=42766205) took some attention as a more pythonesque approach to matching presentation and meaning. I liked it, but it seems that it didn’t catch on, alas.

              • kazinator 2 days ago

                How do you know it didn't catch on? It depends on Lisp! The fraction of programmers using parinfer is bounded by the fraction of Lisp programmers. (I think I might have seen some fledgling experiment with parinfer for other languages, though.)

                I'm highly resistant to novelty in this area, yet even I am using parinfer. A crappy implementation in Vim, at that, which only works in One direction: indent -> parens, and can get into an infinite loop fighting with Vim's undo.

                • harperlee a day ago

                  Well from what I see on the emacs corners of the internet, not so much discussion.

                  Also I recently read on an HN thread I started: it was taken out of Calva due to bugs no one fixed.

              • wink 2 days ago

                Not your fault, but I think it's such a silly argument.

                About 90% of my problems arise when I shift the parens, e.g. going from `(+ (1 2))` to `(+ (+ 1 2) 3)` or the other way round - and if there is now ) or )) at the very end (but more likely at 4+, not 1 or 2.

                How would any plugin know what I mean here? (I know + is a bad example as its commutative...).

                • mtlmtlmtlmtl 2 days ago

                  Paredit has lots of great ways to do that sort of thing, though, while keeping things balanced. In emacs with paredit, providing a prefix argument to open paren lets you surround n sexps in the new parens. There's also slurp and barf to move sexps in and out of parens.

                  Editing for lisp mirrors the language as a whole in that there's a learning curve, but once you've climbed it, it's a joy to work with. Because the syntax is so uniform, all you need is a handful of extensions/commands for full blown structural editing.

                  I get by splendidly in emacs with nothing but paredit and convenient keybindings(not a huge fan of paredit defaults).

                  • ludston 2 days ago

                    You need to clarify your example, because it appears that you are inserting `+` and `3` between existing parens rather than shifting them.

                    But regardless, I think the answer you are looking for is:

                    Some of the coolest kids of all use rainbow delimiters so that they can easily identify the matching closing paren with their eyes!

                    • wink 2 days ago

                      I tried, I'd need to crank the font size up to 14+ to discern the difference ;)

                  • nine_k 2 days ago

                    Writing code is usually easier than reading!

                    • _nalply 2 days ago

                      In Rust I came to the opposite conclusion.

                      One webserver framework, Axum, has the trait IntoResponse which is returned by something that implements Handler. A lot of things implement IntoResponse and/or Handler. In plain English you have handlers, these are parts of code that get selectively invoked for a request. The handlers return data that can be made into responses. It's powerful, but if something doesn't fit exactly, the Rust compiler throws gibberish errors at you. It's finnicky as hell.

                      But once you have written something that works, it is beautiful to read.

                      So it's difficult to write such code, and if it's easy for you then it's because you mastered the art.

                      • ludston 2 days ago

                        If you're not used to the language, the conceptual models of the codebase you are working on, or you're working with obfuscated code. Otherwise it should be much faster to read and understand the code somebody else wrote than to write it from scratch?

                        • nine_k 2 days ago

                          No, I mean, in general, including languages which I work with for 20-25 years. Reading code is still harder than writing.

                          • ludston 2 days ago

                            I can certainly think of examples where reading code is harder than writing it, but given that much of my professional role has been dissecting the horrible code written by other people in order to figure out not only what it does, but also what it was supposed to do, I simply disagree. Reading code is just more boring than writing it.

                      • johnisgood 2 days ago

                        Exactly.

                  • donio 2 days ago

                    For Lisp users this is 35% extra vertical space for zero readability benefit. Or negative readability rather. When I see this formatting style I have to fix it before I can read it. It's like trying to read C code with an extra blank line after every single closing brace.

                    • nine_k 2 days ago

                      Lisp users are a diverse crowd. I won't be so bold as to sign off for all of them.

                      • pasc1878 2 days ago

                        The main reason to use it is not for reading it is to work with version control which is all line orientated.

                        The reading is not that bad as the indentation tells you where the brackets are and you don't really notice them.

                        • undefined 2 days ago
                          [deleted]
                          • aartaka 2 days ago

                            Why 35%? I can't seem to align with you on the math here.

                            • donio 2 days ago

                              You are right, I made the classic mistake of doing the percentage backwards. Once properly formatted I am counting 16 lines and it goes up to 25 so it's a 56% increase.

                          • n8henrie 3 days ago

                            As a hobbyist that keeps trying to break into lisp, I think the absence of an obviously good formatter for lisps has made things much harder.

                            This looks like how I've naively tried to format things, and having started with python kind of makes sense.

                            But trying to read / edit code with 5 parentheses bunched together, I have the hardest time telling if they are matched or where. Thank goodness for vim / helix auto-matching.

                            • skydhash 3 days ago

                              The way to have a good time with lisp is using Emacs and Slime/Sly. And if you like shortcuts, you can try Paredit for structural editing.

                              I just use the Tab key for indenting and it always work for me (there's a logic on where to break line to get correct indenting, and it makes it easy to see if you misplaced a parenthesis. Also, both Emacs and Vim, highlight the matched parenthesis, so I never wonder about if I have the correct number of closing parenthesis.

                              • JBiserkov 3 days ago

                                You can also try "rainbow parens" color scheme that makes nesting much easier to see.

                                • kazinator 2 days ago

                                  You are looking at the wrong thing. Nobody looks at bunched parentheses for any reason, unless they are investigating a suspicion that the code's indentation is wrong. In that situation, all that matters is whether the bunch contains the correct number of parentheses, not which specific closers match which specific openers.

                                    (foo
                                       (bar
                                          (baz (xyzzy arg))
                                       (bar arg))
                                  
                                  We know from the indentation that this is supposed to be a closed unit:

                                       (bar
                                          (baz (xyzzy arg))
                                  
                                  But it needs three closing parens ))) not just )).

                                  If this problem is not accidentally compensated by a ) in the wrong place elsewhere, this code will error out.

                                  One simple thing you can do is just automatically reindent the whole block. The indentation will then match the incorrect parentheses and the problem will be clear. Undo the temporary reformatting and fix it.

                                  • n8henrie a day ago

                                    > One simple thing you can do is just automatically reindent the whole block.

                                    This is exactly the point of my comment -- the absence of an obvious / reasonable automatic formatter is the problem I'm pointing to.

                                    • kazinator a day ago

                                      In Vim, use V to go into line-oriented visual selection mode. Move the cursor over the range of lines to be reindented and hit =.

                                • draven 2 days ago

                                  Admit you posted this only to trigger lispers.

                                  • aartaka 2 days ago

                                    I'm a Lisper myself, lol.

                                  • rayiner 3 days ago

                                    That is blasphemy.

                                    • simplify 3 days ago

                                      You may not like it, but this is what peak lisp indentation looks like :)

                                      Honestly though, this style for ending parenthesis of block-type nodes makes a lot of sense to me. And you still retain the benefit of macro-ing your own syntax when you need it.

                                      • shawn_w 3 days ago

                                        The uncuddled closing parens are a sure sign of a sick mind; probably corrupted by C or the like.

                                        • andriamanitra 2 days ago

                                          They make line-by-line diffs nicer. And it's quite nice to be able to swap/move lines without messing up the closing paren, especially when not using a structural editor.

                                          • varjag 2 days ago

                                            To be fair in C they don't put semicolon on its own line either.

                                            • Pxtl 2 days ago

                                              Maybe they should?

                                              I mean otherwise why not do

                                                  void MyFunc() {
                                                      DoStuff();
                                                      DoOtherStuff();}
                                              
                                              If the close-parens being on its own line is so wrong, why is it right for braces?
                                            • undefined 2 days ago
                                              [deleted]
                                            • DonHopkins 3 days ago

                                              Nicely indented easy to read blasphemy is the most dangerous kind!

                                              • JBiserkov 3 days ago

                                                One thing I dislike about the compact style is how adding/removing a let block causes a diff line that is just adding/removing a parent.

                                                • kazinator 2 days ago

                                                  Do you really think it's just a matter of style whether or not you must add or remove a parenthesis? Or whether that change shows up in a diff?

                                                • nine_k 2 days ago

                                                  A blasphemy is a very useful thing in cases when a discipline turns into a religion. (Yes, I know about jokes.)

                                                  • acheron 2 days ago

                                                    Exactly what I was thinking.

                                                    • aartaka 2 days ago

                                                      That is

                                                    • Avshalom 2 days ago

                                                      More of an allman Lisp guy myself

                                                        (
                                                        define (match:element variable restrictions)
                                                          (
                                                          define (ok? datum)
                                                            (
                                                            every 
                                                              (
                                                              lambda (restriction)
                                                                (restriction datum)
                                                              )
                                                              restrictions
                                                            )
                                                          )
                                                        (
                                                          define (element-match data dictionary succeed)
                                                            (
                                                            and 
                                                              (ok? data)
                                                              (
                                                              let ((vcell (match:lookup variable dictionary)))
                                                                (
                                                                if vcell
                                                                  (
                                                                  and 
                                                                   (equal? (match:value vcell) data)
                                                                   (succeed dictionary)
                                                                  )
                                                                  (succeed (match:bind variable data dictionary))
                                                                )
                                                              )
                                                            )
                                                          )
                                                          element-match
                                                        )
                                                      • maiar 3 days ago

                                                        I’ve been in too many arguments about Lisp indentation but that actually comes close to decent with a couple of changes: move the singleton closing parens up, and reduce to, say, 2 spaces.

                                                        • EFreethought 2 days ago

                                                          I am sure there are some Emacs modes or plugins for other editors that could go back and forth between this and the more commonly-seen style.

                                                          • thiht 2 days ago

                                                            I don't use Lisp but this is very readable to me, actually way more than the examples in the article by a lot. I actually understand this code, just because of how it's formatted. Maybe I'd just use 2 spaces instead of 4 but otherwise, looks good.

                                                            Granted I'm not the one to optimize for since I don't use Lisp, but this just seems sane and easy to automate, and it looks like other non-Lisp languages.

                                                            • undefined 3 days ago
                                                              [deleted]
                                                              • undefined 2 days ago
                                                                [deleted]
                                                                • stackghost 2 days ago

                                                                  Those poor lonely parens!

                                                                  • Pxtl 2 days ago

                                                                    Do the poor lonely braces in Algol-style languages indented OTBS-style bother you?

                                                                    Should we be doing this?:

                                                                        void MyFunc() {
                                                                            DoStuff();
                                                                            DoOtherStuff();}
                                                                    • stackghost 2 days ago

                                                                      Parens are like penguins, they need to snuggle. Get out of here with your vile curly braces.

                                                                  • dmos62 2 days ago

                                                                    The only thing that's missing is moving most of nested logic into `let` assignments.

                                                                    • mcv 2 days ago

                                                                      Yeah, I'm surprised the article doesn't address this obvious case. It's pretty much my default indentation scheme for any language, and while I see a lot of lispers here complain about the wasted vertical space, it's undeniably easy to see which parentheses match and what the block structure is.

                                                                      I'll happily tolerate some wasted space in that trade-off.

                                                                      • Pxtl 3 days ago

                                                                        Honestly that's the indentation format I use for every language. Doing it in Lisp just makes sense.

                                                                        My "OTBS all the things" rules:

                                                                        - Never horizontal align. Indentation is a simple tree, with each set of children indented 1 layer deeper, which can be 4 spaces or 1 tab.

                                                                            ThisKindOfThing(
                                                                                            foo,
                                                                                            bar,
                                                                                            baz);
                                                                        
                                                                        is generally dumb.

                                                                        - If a block is worth indenting for, the end of the block deserves its own line. Just do OTBS but also for parentheses if you've a long function call.

                                                                          ThisKindOfThing (
                                                                              foo,
                                                                              bar,
                                                                              baz
                                                                          );
                                                                        
                                                                        Is just more consistent and easier to manage while still being legible.

                                                                        - if you're ever splitting something across multiple lines there must be an indent.

                                                                          myObj
                                                                              .Foo()
                                                                              .Bar()
                                                                              .Baz();
                                                                        
                                                                        - you're allowed to double-dip on tree depth - that is indent only one level for like 3 levels of tree, as long as the opening of that 3-deep jump is a clear one-liner and the end of it is a line that says ")))".

                                                                          Foo(Bar(Baz(
                                                                              someVal
                                                                          )));
                                                                        
                                                                        - when splitting lines on infix operators, anything but commas go at the start of the line (also, bedmas counts as tree depth)

                                                                          foo
                                                                              + bar
                                                                              + baz
                                                                              + (
                                                                                  var1
                                                                                  * var2
                                                                                  * var3
                                                                              )
                                                                              + quux;
                                                                        • TOGoS 2 days ago

                                                                          This is exactly the set of rules I happen to have ended up using. I suspect this is one of the few styles that you inevitably arrive at if you search the space for a format that looks okay, is easy to read, doesn't cause things to shift around when functions are renamed, and is relatively simple and self-consistent.

                                                                          • b4ckup 2 days ago

                                                                            This is mostly how I indent my code. I don't know why so many people hate it. We have huge screens and spacing conveys structure so I use spacing when appropriate, like a ')' in its own line. I work in a *very* small team though and I write most of the code.

                                                                            • varjag 2 days ago

                                                                              That's pretty awful even for other languages.

                                                                              • Pxtl 2 days ago

                                                                                Is this better?

                                                                                    void MyFunc() {
                                                                                                   DoStuff();
                                                                                                   DoOtherStuff();}
                                                                            • kazinator 2 days ago

                                                                              Once you have even a small amount of that background it's complete shit. Or else if it isn't, nobody wants to work with you. But at that point that probably suits you fine. If you want to work completely alone, yet be maximally productive, you've landed in a good language family.

                                                                              • kleiba 2 days ago

                                                                                Haha, good one!

                                                                                (I hope?!)

                                                                                • varjag 2 days ago

                                                                                  This is one of the most disgusting things I read on HN.

                                                                                • fn-mote 3 days ago

                                                                                  I love a Lisp-themed article, but this is such a yawn in 2025.

                                                                                  It seems pretty clear that a threading macro which allows the user to place the "hole" being filled wherever they want is the answer.

                                                                                  Example: cl-arrows

                                                                                  https://github.com/nightfly19/cl-arrows?tab=readme-ov-file

                                                                                  • kleiba 2 days ago

                                                                                        (tree-transform-if predicate
                                                                                                           transformer
                                                                                                           (second tree)
                                                                                                           depth)
                                                                                    
                                                                                    > A problematic function indentation

                                                                                    > Nineteen! Nineteen spaces of indentation! It's getting unruly.

                                                                                    Why, is there a shortage of whitespace these days??

                                                                                    > Such an indent, when used in deeply nested code, makes it too wide and unreadable.

                                                                                    Ah, I see! Well, I would argue the problem is not the indentation style. What makes your code unreadable is that it's too deply nested, and I would bet that no indentation style can help with that.

                                                                                    • aartaka 2 days ago

                                                                                      That's a point too!

                                                                                    • RedNifre 2 days ago

                                                                                      Are there any formatters that detect related things and put them in the same column? Here's a Pie example:

                                                                                        (claim  Tuple3 (->                U       U     U    U))
                                                                                        (define Tuple3 (lambda          ( a       b     c   )
                                                                                                         (Pair            a (Pair b     c)  )))
                                                                                        (claim  tuple3Of (Pi (           (A U)   (B U) (C U))
                                                                                                          (->             A       B     C
                                                                                                            (Tuple3       A       B     C   ))))
                                                                                        (define tuple3Of (lambda  (       A       B     C   )
                                                                                                           (lambda      ( a       b     c   )
                                                                                                             (the (Tuple3 A       B     C   )
                                                                                                               (cons      a (cons b     c)) ))))
                                                                                      
                                                                                        (claim  Tuple5 (->                U       U       U       U     U    U))
                                                                                        (define Tuple5 (lambda          ( a       b       c       d     e   )
                                                                                                         (Pair            a (Pair b (Pair c (Pair d     e))))))
                                                                                        (claim  tuple5Of (Pi            ((A U)   (B U)   (C U)   (D U) (E U))
                                                                                                           (->            A       B       C       D     E
                                                                                                             (Tuple5      A       B       C       D     E   ))))
                                                                                        (define tuple5Of (lambda        ( A       B       C       D     E   )
                                                                                                           (lambda      ( a       b       c       d     e   )
                                                                                                             (the (Tuple5 A       B       C       D     E   )
                                                                                                               (cons      a (cons b (cons c (cons d     e))))))))
                                                                                      • phoe-krk 3 days ago

                                                                                        > Common Lisp in particular is extremely unfriendly to threading macros. Arrows imply a consistent thread-first or thread-last functions. But CL's standard lib is too inconsistent for that to work. So we're left with picking an indentation style we don't necessarily like.

                                                                                        Diamond arrows exist, you know.

                                                                                            (-<> foo
                                                                                              bar
                                                                                              (baz)
                                                                                              (quux 1 2 3)
                                                                                              (fred 4 5 6 <>)
                                                                                              (frob 7 <> 8 <> 9))
                                                                                        
                                                                                        All in all, this post reads like a rant, and I realized that upon reading "now what I'm about to suggest is likely not to your taste". That style of indentation is something I use often when writing calls to long-named functions like COMPUTE-APPLICABLE-METHODS and I haven't ever thought of it being not to my taste, or even of it being ugly as the author suggests.
                                                                                        • aartaka 2 days ago

                                                                                          Well, it's all based on my experience. In two Lisp companies I worked in, colleagues complained or even were trying to fix how I indent things. So it's not just some anxiety whatever, it's experience that needs explanation and justification.

                                                                                          I'm aware of arrow-macros/diamond wands, and am using them myself. But I often have to write dependency-less libraries for moderately complicated algos, and that's where indentation style is the only thing I can rely on.

                                                                                        • behnamoh 3 days ago

                                                                                              > (tree-transform-if predicate
                                                                                              >                   transformer
                                                                                              >                   (second tree)
                                                                                              >                   depth)
                                                                                          
                                                                                          > A problematic function indentation > Nineteen! Nineteen spaces of indentation! It's getting unruly. Such an indent, when used in deeply nested code, makes it too wide and unreadable. If you add the strict one-per-line alignment of arguments, it's also painfully long line-wise.

                                                                                          I think this is more a problem with languages that encourage (or don't discourage) deeply nested function calls. I face the same issue in Python, although Python kinda discourages me to do:

                                                                                              foo(
                                                                                                  bar(
                                                                                                      baz(
                                                                                                          far(
                                                                                                              faz(...)))))
                                                                                          
                                                                                          
                                                                                          Instead, Python and Pythonic idioms encourage a "step by step" approach:

                                                                                              a = faz(...)
                                                                                              b = far(a)
                                                                                              ...
                                                                                          
                                                                                          
                                                                                          I don't know which is "better"—the first approach requires thinking ahead about the chain of functions we're about to call while the second one is more like a gradual development of the solution, albeit being more verbose than the former.
                                                                                          • UltraSane 3 days ago

                                                                                            The second Python method that uses intermediary variable is what I use because it works much better with a debugger

                                                                                            I also like this trick to avoid nested for loops:

                                                                                              import itertools 
                                                                                              names = ['Bob', 'Sam']
                                                                                              nums = [1,2]
                                                                                              letters = ['A','B']
                                                                                              for name,num,letter in itertools.product(names,nums,letters):
                                                                                                  print(f"{name} {num} {letter}")
                                                                                            
                                                                                              Bob 1 A
                                                                                              Bob 1 B
                                                                                              Bob 2 A
                                                                                              Bob 2 B
                                                                                              Sam 1 A
                                                                                              Sam 1 B
                                                                                              Sam 2 A
                                                                                              Sam 2 B
                                                                                            • phoe-krk 3 days ago

                                                                                              You can have the same step-by-step in Lisp via LET*. The problem outlined by the author happens when you have a function call where 1) the operator has a long name, 2) there are many arguments. The TREE-TRANSFORM-IF is such a case and you can't solve it by just "going step by step".

                                                                                              • behnamoh 3 days ago

                                                                                                Yes, I think for whatever reason, Lisp languages tend to use long names for funcs and vars whereas Haskell and other FP languages prefer symbols like >>=, <$>, etc. Personally, I prefer somewhere in the middle.

                                                                                                > The TREE-TRANSFORM-IF is such a case and you can't solve it by just "going step by step".

                                                                                                Yes, this is a good point.

                                                                                                • skydhash 3 days ago

                                                                                                  Why not just locally bind it to something shorter with let? Lisp is flexible enough that this is a non issue.

                                                                                                  • phoe-krk 2 days ago

                                                                                                    You introduce four new variables. You get five lines instead of four, and four of these lines are pure cognitive overhead.

                                                                                                • Pxtl 3 days ago

                                                                                                  That deep nest of function calls is why I love languages that have bash-style pipelining as a built in feature, either with explicit shell piping features, or where everything Function(myObj) is also implicitly myObj.Method()

                                                                                                  Then it becomes (eg PowerShell, a language I hate but use constantly)

                                                                                                    Faz | 
                                                                                                        Far |
                                                                                                        Baz |
                                                                                                        Bar |
                                                                                                        Foo
                                                                                                  
                                                                                                  Or (more C++/Java/C#-ish)

                                                                                                    Faz()
                                                                                                        .Far()
                                                                                                        .Baz()
                                                                                                        .Bar()
                                                                                                        .Foo()
                                                                                                  
                                                                                                  In this way the data and execution flows forwards instead of backwards and you don't have a pyramid of indentation.

                                                                                                  I don't know why we're so stuck on prefix notation for function calls. Postfix is just easier to read in long chains.

                                                                                                  • sitkack 2 days ago

                                                                                                    In Python you have the wonderful https://github.com/pytoolz/toolz

                                                                                                        from toolz import pipe
                                                                                                        pipe('hello',lambda w: ( "foo", w ), lambda y: [ 0, y, 1 ])
                                                                                                    
                                                                                                        [0, ('foo', 'hello'), 1]
                                                                                                    
                                                                                                    You can used named functions, but they would need to be define above in upper scope

                                                                                                        def h(x):
                                                                                                            return ( "foo", x )
                                                                                                    
                                                                                                        def g(x):
                                                                                                            return [ 0, x, 1]
                                                                                                    
                                                                                                        pipe('hello', h, g)
                                                                                                    • behnamoh 2 days ago

                                                                                                      thanks, I'll check this out. I've seen similar libs before, like "pipes" which also does piping through the "|" symbol.

                                                                                                    • aartaka 2 days ago

                                                                                                      This is a good style indeed, and I'm using it a lot in JavaScript, but you have to admit that it's never as consistent as that—there are basic functions mixed into it, and some lambdas, and whatever.

                                                                                                    • martin-t 3 days ago

                                                                                                      I prefer a third approach - chaining method calls via `.method()`. C#'s LINQ extension methods and Rust's iterator methods do it and I find it to be the best of both worlds most of the time.

                                                                                                      • behnamoh 3 days ago

                                                                                                        So the "fluent design" approach? I like that too, and many OO languages allow for that, but I haven't seen that approach in functional programming.

                                                                                                        • 3836293648 3 days ago

                                                                                                          Really?

                                                                                                          Iterator methods are the only part of Rust/C# that feel like normal decent function composition. Except Haskell is backwards.

                                                                                                    • kazinator 2 days ago

                                                                                                      It's clear that the blogger is a wide-eyed newbie, who is enamored of Lisp and trying to attract any kind of attention and clicks to it. Obviously, it worked; he got on the front page of HN.

                                                                                                      I predict that in another five years, he will write an article disparaging Lisp and purge it from his CV, and that will be that.

                                                                                                      • aartaka 2 days ago

                                                                                                        I literally program in Lisp for five years now, and I ain't going anywhere.

                                                                                                      • kazinator 2 days ago

                                                                                                        I just skipped to the bottom of this crap to find the real gem: it's produced with the help of ed.

                                                                                                        Yeah, someone working with ed its not going to like 19 repeated leading spaces across lines for vertical alignment. They will like that less than even somebody working with Notepad.

                                                                                                        • juped 2 days ago

                                                                                                          ...the author is using ed scripts as a static site generator, in a way completely unrelated to the post content. People are allowed to do oddball things.

                                                                                                          • kazinator 2 days ago

                                                                                                            Oddball things lead to oddball opinions. Like: you have to go to the monstrous effort of repeating nineteen spaces into the next line again and again to achieve this aligned appearance, therefore it looks ugly.

                                                                                                            • aartaka 2 days ago

                                                                                                              That's one way to think of it.

                                                                                                        • lgrapenthin 2 days ago

                                                                                                          > Once you get used to Lisp, you stop noticing the parentheses and rely on indentation instead.

                                                                                                          Who does that? LISP has a datastructured syntax, textformat has no meaning in it.

                                                                                                          • aartaka 2 days ago

                                                                                                            Humans read code. I'd like to become a machine someday, but alas, I still am human and I need to read mine/others' code. Lisp code too.

                                                                                                          • wegfawefgawefg 2 days ago

                                                                                                            idk i always just put a newline before every single open parens and that worked for me

                                                                                                            • agumonkey 3 days ago

                                                                                                              never had any real issue using emacs indentation engine (not even sure lisp modes use smie..)

                                                                                                              • swayvil 3 days ago

                                                                                                                Surely one could do it with different background colors instead. Any examples of that?

                                                                                                                • el_memorioso 3 days ago

                                                                                                                  For matching parentheses, Emacs users can use a package called rainbow-delimiters that colors matching delimiters. Different levels of enclosure use different colors. I've found this to be too much visual noise -- I am usually just interested on the delimiters for the current s-expressions. In this vein, having multiple different colored backgrounds would be garish and distracting for me.

                                                                                                                  • tmtvl 2 days ago

                                                                                                                    I have seen it done with foreground colours: https://github.com/alphapapa/prism.el

                                                                                                                    I think I once saw a project turning Scheme into a visual block-based representation, but I can't find it again.

                                                                                                                  • lincpa 2 days ago

                                                                                                                    [dead]

                                                                                                                    • stevebmark 3 days ago

                                                                                                                      Lisp is an objectively goofy language,* I appreciate someone pointing out the pain points around trying to cobble together readability via indentation.

                                                                                                                      * Not a bad language - well, maybe bad by today's standards, but undeniably a very important language - just goofy

                                                                                                                      • bcrosby95 3 days ago

                                                                                                                        What languages do you use are readable without indentation? I guess other than Python, where indentation actually contributes towards correctness rather than it just being optional.

                                                                                                                        • cb321 3 days ago

                                                                                                                          Well, there is also https://nim-lang.org as well as a pretty big list at https://en.wikipedia.org/wiki/Off-side_rule . Just expanding, not trying to invalidate your valid question!

                                                                                                                          • shawn_w 3 days ago

                                                                                                                            APL?

                                                                                                                            (For certain values of readable)

                                                                                                                            • aartaka 2 days ago

                                                                                                                              But well, it's actually the most readable and meaningful language... to APL programmers.

                                                                                                                          • undefined 3 days ago
                                                                                                                            [deleted]