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

Pattern matching operator #4128

Open
TesteurManiak opened this issue Oct 11, 2024 · 2 comments
Open

Pattern matching operator #4128

TesteurManiak opened this issue Oct 11, 2024 · 2 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@TesteurManiak
Copy link

Suggestion

In Swift, you can change the way pattern matching is handled on an object (or struct) by overloading a pattern matching operator ~=. It would be nice to have a similar feature for Dart objects.

Swift Example

struct Circle {
  var radius: Double
}

func ~= (pattern: Double, value: Circle) -> Bool {
  return value.radius == pattern
}

let myCircle = Circle(radius: 5)

switch myCircle {
  case 5:
    print("Circle with a radius of 5")
  case 10:
    print("Circle with a radius of 10")
  default:
    print("Circle with a different radius")
}

Dart Example

class Circle {
  const Circle({required this.radius});
  
  final double radius;
  
  @override
  bool operator ~=(double pattern) => radius == pattern;
}

final myCircle = Circle(radius: 5);

switch (myCircle) {
  case 5:
    print("Circle with a radius of 5");
  case 10:
    print("Circle with a radius of 10");
  default:
    print("Circle with a different radius");
}
@TesteurManiak TesteurManiak added the feature Proposed language feature that solves one or more problems label Oct 11, 2024
@hydro63
Copy link

hydro63 commented Oct 11, 2024

Very similar to functions as patterns as proposed in #4057.

The referenced issue talks about allowing delagating pattern matching to a function, where the function would also be able to return T? instead of just bool. That allows it to be used in destructuring, not just testing, since you can just bind the returned value, and if it's null refute the pattern.

@lrhn
Copy link
Member

lrhn commented Oct 13, 2024

This example doesn't really motivate this operator, and the linked documentation also doesn't give any examples of why it's necessary. It says it enables using in case switches, but you can use any object in case patterns in Dart using object patterns.

That is:

switch (myCircle) {
  case Circle(radius: == 5):
    print("Circle with a radius of 5");
  case Circle(radius: == 10):
    print("Circle with a radius of 10");
  default:
    print("Circle with a different radius");
}

It's longer, but more explicit.
(If you implement operator == of Circleto be equal to doubles, then it works like what you ask for. You shouldn't because, it's not symmetric.)

A function that does equality does not work with nested patterns, not unless we have first class patterns.
(It cannot do the equivalent of Circle(radius: < 5).)

The alternative in Dart would be an automatic coercion, where a pattern match against a Circle would automatically read the radius getter, and then let pattern matching work on that instead.
Dart generally doesn't do automatic coercions.

It was discussed while developing patterns, that a class could have an implicit coercion to a record, so you could match against that in a pattern match.
Object patterns make that unnecessary. You can give the class a normal getter returning that record and write TheClass(theGetter: pattern) and get the same effect without the implicit coercion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants