1. 11
    type declaration syntax citrons.xyz
  1.  

    1. 6

      I have to recommend Ginger Bill's take on the subject. I feel the differences it captures are more meaningful, though this article does have a couple things that stood out to me.

      The mention of juxtaposition comes to mind: that complete absence of syntax, where one or more elements are just written one after another, with nothing but whitespace between them. Many languages fail to use it, or use it only anecdotally. But as the lightest syntax of them all, I feel it should on the contrary be front and centre.

      • The champion there would be Forth, I think. Its primary composition mechanism, sequencing, is used absolutely everywhere, and the separator for that is just nothing at all — or whitespace.
      • Statically typed functional languages (ML, Haskell…) have a similar strategy, except this time with function calls. The savings aren't as impressive as they are with Forth though, because of all the parentheses this often entail. Compare for instance f(x+y, z) and f (x+y) z.
      • One I almost overlooked, but very much love, is the optional semicolon. Unless your language has significant whitespace, omitting the semicolon is the same as juxtaposing instructions. Though of course, this time juxtaposition has the lowest priority. (In ML it's the highest.)
      • Another I hardly ever see it used are list/array literals. Just get rid of the separator, most coding rules want you to add a space after the coma anyway: [1 2 3 5 8]. I would probably not do the same to function calls though: f(x+y z g(a b)) is not ambiguous, but unlike arrays nested expressions are much more common, and the lack of visual separation might be unreasonable.

      This whitespace business taught me a valuable lesson: to the extent it doesn't hurt something else you care about, the lightest constructs should go to the most used features, and the heaviest to the rarest. Helps pack more code in fewer characters, even fewer lines (it matters), without cluttering your screen full of line noise.

      It's also a big reason why I wan on board with Jonathan Blow's idea of not committing to a given syntax from the get go: you gotta get a feel for how you are using (or want to use) your language first. Once you've measured things a bit you can start making adjustment. Beware syntax induced biases though, where you end up using something more or less just because of your initial syntactic quirks.

      1. 2

        there is something almost meditative about forth-style concatenative syntax. there's just one thing and then there's another thing. I like the clarity of that.

        when I wrote about juxtaposition, I was thinking about lua, where there is no syntactic delineation of statements; it's just completely ambiguous without any form of separator.

        1. 2

          it's just completely ambiguous without any form of separator.

          That's the magic: it's not! The parser knows exactly where to separate statements! Though it does disagree with humans when the latter instruction starts with an open parenthesis (it can look like a function call). So… yeah, kinda ambiguous. Thankfully the newline is an excellent visual separator.

          1. 2

            oops, I meant t type "unambiguous" :)

      2. 6

        This article sent me off on a failed investigation!

        The type variable syntax goes back to Algol.

        The variable: type syntax is harder to track down. Pascal is perhaps the earliest well-known language that uses it, but I haven’t found anything that says how Wirth came to choose a different syntax from Algol. The obvious “why” is that Pascal has a much richer type syntax which would make type-first variable declarations unwieldy, and the obvious “what” is that he was copying mathematical precedent. But I would like to know exactly which precedent: any specific texts on logic? I don’t know of any good sources on the history of mathematical notation and I don’t know enough about what kinds of notations would have been used as inspiration by programming language designers in the late 1960s.

        WRT functional programming languages, AFAIK in the late 1960s they were dynamically typed (eg, ISWIM) so I didn’t find a notation for type annotations there.

        IIRC Haskell swapped the choice of : vs :: for type ascription and cons because when it was designed they expected cons to be used a lot more (especially for teaching introductory programming to undergrads) so cons got the shorter spelling. Type ascriptions can be written in expressions as well as in declarations, so they must not collide with the cons operator.

        1. 0

          Oh no, this is slop. “Load-bearing”…

          1. 4

            I don't know. I read through every word and it didn't send off any flags in my head.

            1. 2

              it is interesting and flattering to have my words pored over and inspected. it tingles. I assure you that every character was emitted from the waggling of my finger into a keystroke, faithfully recorded by the "vis" text editor. if I kept up too closely with LLM tics, I may be unduly influenced by them :)

              whether or not you enjoy my work here is another matter; I did make it in only a few hours.

              1. 1

                P.S. I should explain my thought process. the article is really a segment of a long train of thought I have about designing my own programming language. there is an infinite set of minutiae when it comes to syntax, and well, I love minutiae. I say "load-bearing" here because, even though with a second thought, the colon is not actually that important in python, it would be in the absence of significant whitespace. which is another thing I've thought about.

                if (a) b // c
                if a {b} // go
                if a: b // python-ish
                

                you only need one token to separate the antecedent from the consequent, and said token is "load-bearing," like a stud in a wall. you need it there. in the C example, however, you don't need the (. it is not load-bearing. my diction reflects my thought process.

              2. 1

                Understandable reaction, but it's a tired phrase among Rationalist fans (long before LLMs.) I agree with @Halkcyon the article doesn't trigger my slop detector.