Open Skquark opened 4 years ago
I found myself using this a few times. Although I think pattern matching
or at least a switch case with return type
will land in Dart in the next 2 years, this can work as a neat temporary solution.
I'd like to hear your opinion on a slightly different API. When I use this pattern I use Functions as my cases. The trailing braces ()
in your API don't look nice. I'm also not 100% satisfied with the default argument. I wish it would be a named argument but as default
is a reserved word, that's kind of impossible.
??
is strange()
to the end defaultValue
param better formatted. But using ??
has the same effect with less allocations// Original Proposal
_counter.switchCase({
1: Text("It's one"),
2: Text("It's two"),
3: Text("It's three"),
}) ??
Text("Other number"),
// Original Proposal with default
_counter.switchCase(
{
1: Text("It's one"),
2: Text("It's two"),
3: Text("It's three"),
},
Text("Other number"),
),
// Original Proposal with functions
_counter.switchCase(
{
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
},
() => Text("Other number"),
)(),
()
??
dartformat handling// Proposal 2 - forced functions
_counter.switchCase2({
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
}) ??
Text("Other number"),
// Proposal 2 with default
_counter.switchCase2(
{
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
},
fallback: () => Text("Other number"),
),
defaultTo
match()
is boilerplate compared to Original solutionmatch()
for some reason. Maybe because of Pascals begin/end? 🤷 ??
formatting, but users don't have to use it.// Proposal 3 - match or error
_counter.switchCase3({
0: () => Text("zero"),
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
}).match(),
// Proposal 3 - no default, but null (dartfmt 😖)
_counter.switchCase3({
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
}).matchOrNull() ??
Text("Other number"),
// Proposal 3 with explicit default
_counter.switchCase3({
1: () => Text("It's one"),
2: () => Text("It's two"),
3: () => Text("It's three"),
}).defaultTo(() => Text("Other number")),
Not that interesting, and very likely to change.
extension switchInt on int {
T switchCase<int, T>(Map<int, T> cases, [T defaultValue]) {
if (cases.containsKey(this)) return cases[this];
return defaultValue;
}
T switchCase2<int, T>(Map<int, T Function()> cases, {T Function() fallback}) {
if (cases.containsKey(this)) return cases[this]();
if (fallback == null) return null;
return fallback();
}
SwitchCase<T> switchCase3<int, T>(Map<int, T Function()> cases) {
if (cases.containsKey(this)) return SwitchCase.match(cases[this]());
return SwitchCase.noMatch();
}
}
class SwitchCase<T> {
SwitchCase.match(this.value) : matched = true;
SwitchCase.noMatch()
: matched = false,
value = null;
final T value;
final bool matched;
T match() {
if (matched) return value;
throw "no default argument";
}
T matchOrNull() {
if (matched) return value;
return null;
}
T defaultTo(T Function() fallback) {
if (!matched) return fallback();
return value;
}
}
Does someone have more ideas?
Hmm, I like some of your implementations, but not sure if those proposals really improve it's ease of use over the original. The goal would be as little typing as possible, without extra fields needed, and adding the additional syntax for the optional defaultValue seems to complicate it visually. I agree about there being another way to do the switch case more integrated into the Dart language in the way that the if's are like isTrue ? true : false with an inline method and some creative syntax (I've tried to visualize the best format of that for years), but until then this is a nice simple shortcut method. You could include more than one implementation method so users can pick which switch they prefer for their case. If I had to choose, I liked Proposal 2 with default Maybe there's another simple option too, I'm thinking about it but your call what goes in your package..
I just adapted a little utility I've been using to work as extension, and I think it'd fit in well with your library. It does the equivalent of switch(string) { case "txt1": etc, only cleaner and easier inside a widget structure, or wherever you'd use a standard switch case break default statement.. Here it is:
Simple and fairly elegant code with the optional default: parameter, I could give you the original generic TOptionType version as well (I didn't write it), but it's nicer as extension on String and int and maybe another type too. Feel free to add it in, or if you prefer, I can add it in myself with a PR with doc updates. I'm just loving the flexibility of Dart now, so many new toys to play with...