-
Notifications
You must be signed in to change notification settings - Fork 205
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
Can patterns match an enum field? #2844
Comments
Yes. You can't match directly on
It's a little hard with your particular example because you're getting strings from JSON and not converting them to enum values first, but the integer values for each enum value are also not stored in constants. Even without patterns, you'd have similar problems trying to write this code today using a switch statement. With the new pattern stuff, you could do: switch (json) {
case {'difficultyId': int id} when id == Difficulty.easy.id:
print("Got easy!");
case {'difficultyId': int id} when id == Difficulty.medium.id:
print("Got medium!");
case {'difficultyId': int id} when id == Difficulty.hard.id:
print("Got hard!");
default:
throw Exception('Id must be 1,2 or 3');
} That's fairly verbose (though still better than what you'd write today). Really, the map patterns aren't accomplishing much since you're only accessing a single element and it's always the same one in each case. Maybe better as: switch (json['difficultyId']) {
case int id when id == Difficulty.easy.id:
print("Got easy!");
case int id when id == Difficulty.medium.id:
print("Got medium!");
case int id when id == Difficulty.hard.id:
print("Got hard!");
default:
throw Exception('Id must be 1,2 or 3');
} Or even (pretty weird): var id = json['difficultyId'];
switch (null) {
case _ when id == Difficulty.easy.id:
print("Got easy!");
case _ when id == Difficulty.medium.id:
print("Got medium!");
case _ when id == Difficulty.hard.id:
print("Got hard!");
default:
throw Exception('Id must be 1,2 or 3');
} But, really, I'd do: enum class Difficulty {
static Difficulty fromId(int id) => const {
1: Difficulty.easy,
2: Difficulty.medium,
3: Difficulty.hard,
}[id] ?? throw ArgumentError('Id must be 1,2 or 3');
easy(1, "Easy"),
medium(2, "Medium"),
hard(3, "Hard");
const Difficulty(this.id, this.designation);
final int id;
final String designation;
} And then: switch (Difficulty.fromId(json['difficultyId'])) {
case Difficulty.easy: print("Got easy!");
case Difficulty.medium: print("Got medium!");
case Difficulty.hard: print("Got hard!");
} |
@munificent Really appreciate your answer, even more because this issue is closed 🙂. To be fair I simplified the example, I am using this example on server side dart. I would like to pattern match multiple variables only when You are right that this is not a enum Difficulty {
easy(1, "Easy"),
medium(2, "Medium"),
hard(3, "Hard");
// I think this is a safer approach, if we add a new difficulty.
static Difficulty? fromId(int id) => Difficulty.values.firstWhereOrNull((d) => d.id == id);
const Difficulty(this.id, this.designation);
final int id;
final String designation;
}
class Game {
final Difficulty difficulty;
final int levels;
final String name;
Game(this.difficulty, this.levels, this.name);
}
void main() async {
final json = jsonDecode('{"name": "name, "levels": 100, "difficultyId": 1}');
if (json case {
'name' : final String name,
'levels' : final int levels,
'difficultyId': final int difficultyId,
} when (final difficulty = Difficulty.fromId(difficultyId) != null)) {
final game = Game(difficulty, levels, name);
// insert game and return 200 ok
}
//return 400 bad request
} I would like to avoid |
One thing that would help here is if you could call an arbitrary conversion function in the middle of pattern matching and destructuring. F# has something called active patterns that let you do this and Scala lets you define your own extractors. I had hoped to get something similar into Dart (and initial versions of the proposal had something along those lines) but it didn't pan out. I still hope we can get it in as a last extension because as you note, they come in handy in some cases like this. |
Nice, that seems to solve this particular problem in a more generic way (allowing many more use cases). Fingers crossed and looking forward for that feature. If it happens I hope it gets a more Darty syntax tho 😄. |
Trying the latest dart version I came across this example:
Is there an alternative syntax that can solve this problem or this is not possible at all?
Edit:
Is this the correct solution?
Still don't know how to express this statement (check case
{'difficultyId': int difficultyId}
and multiplewhen
branches):The text was updated successfully, but these errors were encountered: