destructuringponylang

Can you unpack values in pony pattern matching?


Pony has the ability to pattern match on classes and also assign results in match expressions (with let ... :), but is there a way to unpack values in match expressions? For example something like this?

actor Main
  fun f(x: (Foo | Bar)): String =>
    match x
    | Foo(1) => "one"
    | Foo(2) => "two"
    | Foo(x) => x.string() // fails
    else
      "Bar"
    end

The only alternative I can think of is a series of

actor Main
  fun f(x: (Foo | Bar)): String =>
    match x
    | Foo(1) => "one"
    | Foo(2) => "two"
    | Bar => "Bar"
    else
      try
        let f = x as Foo
        f.number.string()
      end
    end

But that doesn't read as well, especially if there are multiple possible classes to match on.


Solution

  • I assume you have accompanying definitions like this:

    class Foo is (Equatable[Foo box] & Stringable)
      var value: I32 = 1
      new create(value': I32) => value = value'
      fun box eq(other: Foo box): Bool => value == other.value
      fun string(): String iso^ => value.string()
    
    primitive Bar
    

    Then you can bind names for whole values of a certain type, like this:

    actor Main
      fun f(x: (Foo | Bar)): String =>
        match x
        | Foo(1) => "one"
        | Foo(2) => "two"
        | let x': Foo => x'.string()
        else
          "Bar"
        end
    

    I think this is not too bad in this particular case, but it's certainly not a true destructuring bind. Pony supports such patterns only for tuples, of the form (let first: First, let second: Second).