1. 8
  1.  

  2. 13

    Even for IRs, this article seems to say “tagged unions are better and more ergonomic, but you can live without them” (including the exhaustiveness checking mentioned at the end). So it’s not really “overrated”, just “you can write code without them, with more pain” which holds for almost all PL constructs.

    1. 8

      Yeah alternative title: “tagged unions are great and you should emulate them in languages that don’t natively support them”

      1. 2

        I’ve mentioned this a bunch of times, but for those who haven’t seen it, Oil uses the same DSL as Python to describe “tagged unions”, called Zephyr ASDL.

        https://www.oilshell.org/blog/2016/12/11.html

        https://www.oilshell.org/blog/tags.html?tag=ASDL#ASDL

        Right after I put it into the codebase I saw how much better the code was structured (even without pattern matching). And it continues to grow more useful after 4 years.

        It can now even express relationships that Rust can’t, i.e. what I’d call “first class variants”: https://github.com/rust-lang/rfcs/pull/2593

        (and it doesn’t have the ergonomic issues with boxing, etc.)

        In Oil’s case it compiles to BOTH statically typed Python and C++. It works in both cases. Objects and subtyping are sort of “dual” to sum types.

        So the bottom line is that you can code in an imperative language (Python, Java, C++), and still structure your compiler nicely. You can have the best of both worlds!

      2. 6

        … for implementing IRs

        Just for completion’s sake, the author should rename make it clear in the post title, not at the end of it. There’s no point to inflame spirits more than it should

        1. 3

          Buttondown is a newsletter service, so the audience are people who subscribed to him and received it as emails. I personally give a lot more leeway for clickbaity email titles than clickbaity blog titles.

        2. 3

          This is inline with my experience. In rust-analyzer, we don’t use enums for concrete syntax tree. We rather go in the opposite direction, and emulate dynamic cast in Rust, as that’s more useful for many IDE tasks. At the same time, there are some selected places where we add a small enum for exhaustivity, and that helps a lot.

          Without thinking to much, I think the value of closed enum (in contrast to an open interface) is inversely proportional to the number of variants. Two variant Option is an absolute life-saver, while n-variant Expr not so much,

          1. 3

            I would like to know why the author thinks so poorly of the visitor pattern. Having written a small compiler in C++, I have made extensive use of that design pattern and had a great experience doing so.

            1. 2

              tagged unions save me from two kinds of bugs :

              1. in exhaustive matches
              2. inconsistent state

              I was waiting for the article to show me how to avoid those without tagged unions. It appears the answer is fuzzing?

              Well, yeah, static analyseses become less valuable at you get closer to exhaustive testing. Tagged unions are a static analysis, and fuzzing a compiler pass is really close to exhaustive testing.

              Am I missing something?

              1. 1

                For those as confused as I, “IR” stands for “intermediate representation”.