Pattern matching + Enum proposals

@clattner I have a simplified proposal that is actionable immediately, and still preserves the future opportunities that Owen and I care about.

When you wrote your initial PR, you required case fields to be named. You later changed your mind. Here’s what you said:

In short: I think the syntax in your initial PR was the right choice! It’s just the desugaring we need to iron out.

Let’s repaint my case struct syntax using your original syntax. For reference, here’s case struct:

enum Color:
    case Red
    case Green
    case Blue

    @fieldwise_init
    case struct RGB:
        var r: Int32
        var g: Int32
        var b: Int32

    @fieldwise_init
    case struct HSL:
        var h: Int32
        var s: Int32
        var l: Int32

We can repaint it using your original PR’s syntax as follows:

enum Color:
    case Red
    case Green
    case Blue
    case RGB(var r: Int32, var g: Int32, var b: Int32)
    case HSL(var h: Int32, var s: Int32, var l: Int32)

That’s a lot more concise!

I’ve made one small change to your original syntax: I’ve added var in front of each argument. This seems important for a few reasons:

  • It matches the syntax of field declarations in structs: we declare fields using var, to indicate ownership.
  • It reflects the signature of Color.RGB.__init__: the initializer takes ownership of its arguments.
  • It leaves open the possibility of supporting trait conformances on cases, e.g. case Foo(var x: Int)(SomeTrait). The presence of var in the field list makes it clear to both human readers and Mojo’s parser that the first bracket introduces a field list, not a trait conformance list.

Some day, we might also want to use this var syntax as shorthand for declaring structs that have the @fieldwise_init decorator. This makes the case syntax “less special”:

struct Point(var x: Int, var y: Int)

var p = Point(0, 0)   # fieldwise initializer is available

match p:
   case Point(x=a, y=b): ...   # pattern matching is available

For the enum MVP, this covers all of the syntax that Owen and I need as the foundation for a future “type-based” treatment of enum cases. If you were to ship this syntax (i.e. the syntax of your initial PR!) for the MVP, we leave open the possibility of (some day) pursuing the opportunities I presented in my feedback post, without needing to redesign the syntax and mental model of enums to accommodate it.

For the MVP, I don’t really mind whether each case desugars to its own type or not. You can implement whatever desugaring you already had in mind. My goal is just to have the MVP design be forward-compatible with the opportunities Owen and I presented. The above syntax sets us up for that. All I need is for the components of each case to be “field-like”, i.e. accessible by name, rather than being “Tuple-like”.