1. 29

  2. 7

    I’ve wanted to see a language with a 2-armed while statement for a while.

    In C-ish syntax, we have the classic while loop: while (condition) { things(); } and the do-while loop do { things(); } while(condition);, depending on whether to check the condition at the beginning or the end.

    However, I’d love to see a combination of the two: do { some_things(); } while(condition) { other_things();}, which would have similar semantics to while(true) { some_things(); if(!condition) break; other_things();}.

    The two-armed while has the benefit of making it clearer where the loop condition is tested and satisfying colleagues that are picky about while loops that appear infinite, while nicely unifying the two types of while loop and being completely backwards compatible with traditional C syntax. The only cost is that you’d lose the ability to emit a diagnostic if you forget the ; after a do-while loop.

    (for the nitpickers, yes, Forth has this in the form of its BEGIN WHILE REPEAT construct. However, Forth tends to be a difficult sell in most development shops)

    1. 6

      Common lisp has this. E.G.:

        with x = 3
        do (format t "a~%")
        until (zerop (decf x))
        do (format t "b~%"))

      This prints a b a b a.

    2. 3

      The first point sounds a bit like Swift’s ExpressibleByStringInterpolation. https://davedelong.com/blog/2021/03/04/exploiting-string-interpolation-for-fun-and-for-profit/

      1. 3

        Two other options for embedding logic programming are miniKanren and CHR. These embeddings have very different behavior; miniKanren is shaped like the author’s desired system, but CHR is more like a tuple space or embedded database which can be queried and updated alongside imperative actions.

        1. 1

          CHR is a really interesting system and I wish there were more literature or examples of usage. I used it once to complete an interesting “missing data” puzzle, and I started a Sudoku solver with it. It seems to be a nice fit when you have a morass of data which you want to sort of massage into information until things coalesce and you find a solution.

        2. 2

          The quasi-literal syntax reminds me (just coincidentally) of the hoops I jumped through in dpdb to get different types of parameter interpolation strings …interpolated.

          1. 1

            The same way we have keyword arguments, I want keyword return values.

            1. 2

              Dafny has this! You can write method foo(param1, param2) returns (x: Int, y: Thing) and then the final values of x and y in the function body are automatically returned.

            2. 1

              Back in the late ‘80s I was experimenting with languages for implementing text adventures / interactive fiction, and I did some thinking about goal-oriented programming (but never built anything.) I believe the Inform 7 language did implement this. It’s very useful both for “do what I mean” command processing (“OPEN RED DOOR” ⟶ take red key out of pocket, unlock door with red key, open door) and for modeling the behavior of NPCs.

              1. 1

                While this was a thought-provoking read, I don’t see benefits of bringing any of these into a language:

                • The tagged templates feature can be implemented as a library with a single indirection of giving names to expressions (which is usually a good style anyway). Alternatively, this can be implemented via macros/code generation.

                • Datalog/Prolog can be implemented as a DSL: the DSL handles the logic part, its implementation control and interaction.

                • Teleo-reactive programs are kind of interesting: they can be implemented as a DSL again, as a library that takes a DAG of dependencies and actions and plans their execution.

                • Finding an execution plan automatically sounds too abstract to be generally useful. It can be useful when constrained to finite domains with clear structure (SQL queries as a successful example), but falls short for a general-purpose language runtime with potentially non-terminating computation. Again, that would be better off as a library/DSL integrated with specific datasets/domains, not a language feature.

                All of these ideas deal with programs’ run time, not compile time (unless they are an implementation detail of a compiler/macro). Having a separate syntax for something (an external DSL) usually means more unnecessary complexity in tooling, specification, interoperability, etc. Language microfeatures are useful to sooth specific, immediate and frequent programmer’s inconveniences: automatic planning/teleo-reactive programs/logic programming are not that.