Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match expressions should support comparing against values too, not just types #231

Closed
kengorab opened this issue Dec 13, 2020 · 1 comment

Comments

@kengorab
Copy link
Owner

kengorab commented Dec 13, 2020

Right now, we can write a match expression which attempts to match a given target against types; it should also be possible to compare it against different values of a type. For example:

val s = "N"

match s {
  "N" => y -= 1
  "S" => y += 1
  "E" => x += 1
  "W" => x -= 1
}

When used as a statement, we don't need to enforce the presence of the wildcard/catchall branch _ => ...; when used an expression, it should be an error to not include it:

val newLoc = match s {
  "N" => [x, y - 1],
  "S" => [x, y + 1]
  _ => [x, y]  // <-- This is required, since it's an expression
}

If the target is of a complex type (say String | Int), values of any constituent type should work:

func sixTwoFour(): String | Int = 624
match sixTwoFour() {
  "Hello" => println("hello!")
  12 => println("twelve")
  624 => println("this is the branch that should be taken")
  _ v => println("type of 'v' is 'String | Int'")
}

It is also possible to have type-specific catchall blocks, though the ordering of these could result in an unreachable code error:

func sixTwoFour(): String | Int = 624
match sixTwoFour() {
  "Hello" => println("hello!")
  String s => println("got string " + s)
  Int i => println(i)            // <-- This is an error, since all following blocks will be unreachable
  12 => println("twelve")
  624 => println("this is the branch that should be taken")
  _ v => println("type of 'v' is 'String | Int'")
}

Up for debate on whether this should be punted, it should also be possible to match against destructured values, eg

val coord: String | Int[] | (Int, Int) = (1, 2)
match coord {
  [1, ...rest] => {}
  [x, None] => {}
  [x, ...xs] => {}
  [head, ..._, tail] => {}      // <-- This should be unreachable (this may actually be very hard to detect.........)
  (1, y) => {}
  (x, 3) => {}
  (1, 3) => {}      // <-- This should be unreachable, since if `coord = (1, 3)`, it'd have been caught in the `(1, y)` case
  (x, y) => {}
  (_, y) => {}      // <-- This should be unreachable as well
  String s => {}
}

This adds a ton of complexity to the typechecker (and probably compiler as well), so I'll have to determine later if it's worth it. Note that it adds a decent amount of complexity to the code as well; for example, it may not be obvious that the value (1, 3) would be handled by the (1, y) => {} case and not the (x, 3) => {} case (since the (1, y) case appears first).

@kengorab
Copy link
Owner Author

kengorab commented May 7, 2021

This can be closed in favor of #314

@kengorab kengorab closed this as completed May 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant