← Back to context

Comment by justinpombrio

12 days ago

I complain about parentheses, and yet I'm building a structure editor[1]. Two complaints about parentheses:

- Parentheses obscure the structure of the language. When different syntax is used for different parts of the language, it's easier to visually scan the code. This is simply because punctuation/arrows/etc. visually stand out more than plain identifiers.

- Parenthetical languages have just as much syntax as non-parenthetical languages, it's just a shittier syntax. Try writing (let (x 1) (y 2) (+ x y)) and see what happens: it's a syntax error. Look at the indentation rules in DrRacket: there's let-like, cond-like, etc., because all of those constructs have different syntax. But it all kind of blends together in a sea of parens.

This weakness of paren-heavy languages is also their greatest strength, though. Since the syntax is so generic, it's easy to extend, and these language extensions can be indistinguishable from the base language. That's a big deal!

BTW, what structure editor would you recommend? Which have you tried?

[1] https://github.com/justinpombrio/synless

I run emacs, so I messed around with paredit and friends.

I can understand your pov as a professional coder, doing enough coding that you can really master the syntax of your language of choice. I code occasionally for scientific research, and the less syntax I have to remember, the better. Little syntactic constraint in combination with structural editing really is a killer feature in my context.

  • paredit is what I think of as a half-structural editor. It gives you some structural shortcuts, but the cursor is still on a character instead of on a node, IIRC. My bet (that I've spent a lot of time building an editor for) is that the big gains will come when the cursor is never on text, always on an AST node.

    > the less syntax I have to remember, the better

    Part of my point is that parenthetical languages don't actually have that much less syntax. You have to remember one of these two syntaxes:

        let x = 1;
        let y = 2;
        do_stuff
    
        (let
          ((x 1)
           (y 2))
         do_stuff)
    

    Now you say that there's a lot more possible variation in the first case; it could be:

        let x = 1; # Rust
        var x = 1; # JS
        x=1 # bash
    

    And I point out that there's a lot of possible variation in the second case too:

        (define x 1) (define x 2) do_stuff
        (let (x 1) (y 2) do_stuff)
        (let x 1 (let y 2 do_stuff))
    

    There is less syntax with parens. But it's not zero syntax, and you still need to memorize it.