Day 4: Switch Expressions & Pattern Matching
Replace messy if-else spaghetti code with elegant switch expressions that force you to handle every scenario and make your logic bulletproof.
မင်္ဂလာပါ.. 👋
100 days of Flutter ရဲ့ Day 4 က ကြိုဆိုပါတယ်။ ဒီနေ့မှာတော့ dart langauge နဲ့ ပတ်သက်တာတွေကို ဆက်လက်ပြီး လေ့လာသွားပါမယ်။ ဒီနေ့ဆွေးနွေးသွားမယ့် ခေါင်းစဥ်တွေကတော့
- Switch Statement
- Switch Expression
- Pattern Matching
တွေပဲ ဖြစ်ပါတယ်။
Switch Statement
Switch ဆိုတာကတော့ ကျွန်တော်တို့တွေ value တခုကို အမျိုးမျိုး စစ်ဖို့ လိုအပ်တဲ့အခါ အသုံးပြုပါတယ်။ အောက်မှာ ပြထားတဲ့ ဥပမာဆိုရင်တော့ ဝင်လာတဲ့ day value ကို အမျိုးမျိုး စစ်ပြီးတော့ ဆိုင်ရာ နေ့ကို return ပြန်ပေးပါတယ်။ switch ကို သုံးခြင်းအားဖြင့် ကျွန်တော်တို့ if/else တွေအများကြီး ရေးဖို့ မလိုတော့ပါဘူး။
void main() {
print("Day 3 is ${getDay(3)}");
print("Day 5 is ${getDay(5)}");
print("Day 6 is ${getDay(6)}");
}
String getDay(int day) {
String result;
switch (day) {
case 1:
result = 'Monday';
break;
case 2:
result = 'Tuesday';
break;
case 3:
result = 'Wednesday';
break;
case 4:
result = 'Thursday';
break;
case 5:
result = 'Friday';
break;
default:
result = 'Weekends';
}
return result;
}
// Output:
// Day 3 is Wednesday
// Day 5 is Friday
// Day 6 is Weekendsတကယ်လို့ switch logic ပြီးတာနဲ့ logic က ပြီးသွားပြီဆို break တွေ မသုံးတော့ဘဲ တခါထဲ return statement နဲ့ ရေးလို့ရပါတယ်။
void main() {
print("Day 3 is ${getDay(3)}");
print("Day 5 is ${getDay(5)}");
print("Day 6 is ${getDay(6)}");
}
String getDay(int day) {
switch (day) {
case 1:
return 'Monday';
case 2:
return 'Tuesday';
case 3:
return 'Wednesday';
case 4:
return 'Thursday';
case 5:
return 'Friday';
default:
return 'Weekends';
}
}
// Output:
// Day 3 is Wednesday
// Day 5 is Friday
// Day 6 is WeekendsSwitch Expression
Switch ကို အပေါ်မှာ ပြခဲ့သလို statement အနေနဲ့ မဟုတ်ဘဲ expression အနေနဲ့လဲ သုံးလို့ရပါသေးတယ်။
Expression အနေနဲ့ သုံးမယ်ဆိုရင် အောက်က ကွာခြားချက်လေးတွေ သတိပြုပေးဖို့ လိုပါတယ်။
- Colon
:အစား Arrow Syntax=> breakအစား Comma,defaultအစား Underscore_
expression ကို သုံးမယ်ဆို ရေးရတာ ပိုပြီးတော့ တိုသွားတာကို အောက်မှာပေးထားတဲ့ ဥပမာတွေမှာ ကြည့်နိုင်ပါတယ်။
void main() {
print("Day 3 is ${getDay(3)}");
print("Day 5 is ${getDay(5)}");
print("Day 6 is ${getDay(6)}");
}
String getDay(int day) {
return switch (day) {
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
_ => 'Weekends',
};
}
// Output:
// Day 3 is Wednesday
// Day 5 is Friday
// Day 6 is Weekendsရိုးရိုး switch မှာဆိုရင် equal ဖြစ်မဖြစ်ကိုပဲ check လို့ရပေမယ့် expression မှာဆိုရင်တော့ အခြားသော equality checks တွေ >, <, ==, !=, >=, <= ပါ လုပ်လို့ရပါတယ်။
void main() {
print(gradeStudent(40));
print(gradeStudent(75));
print(gradeStudent(100));
print(gradeStudent(-1));
}
String gradeStudent(int score) {
return switch (score) {
100 => 'Perfect! 🎉',
>= 90 => 'A - Excellent',
>= 80 => 'B - Good',
>= 70 => 'C - Average',
>= 60 => 'D - Pass',
< 60 && > 0 => 'F - Fail',
_ => 'Invalid score',
};
}
// Output:
// F - Fail
// C - Average
// Perfect! 🎉
// Invalid scorevoid main() {
print(getSeasonType('Jan'));
print(getSeasonType('Jul'));
}
String getSeasonType(String month) {
return switch (month) {
'Dec' || 'Jan' || 'Feb' => 'Winter',
'Mar' || 'Apr' || 'May' => 'Spring',
'Jun' || 'Jul' || 'Aug' => 'Summer',
'Sep' || 'Oct' || 'Nov' => 'Fall',
_ => 'Invalid month',
};
}
// Output:
// Winter
// SummerPattern Matching
Pattern matching အကြောင်းဆက်ပြီး မလေ့လာခင် pattern ဆိုတာ ဘာလဲ သိဖို့လိုအပ်ပါတယ်။ တကယ်လို့ အသေးစိတ် နားလည်ချင်တယ်ဆို Day 3 မှာ ရှင်းပြထားတာကို သွားကြည့်လို့ ရပါတယ်။
လေ့လာပြီးခဲ့သလောက် dart knowledge နဲ့ response code ကနေ message ပြောင်းတာ ရေးမယ်ဆို အခုလို ထွက်လာမှာပဲ ဖြစ်ပါတယ်။
void main() {
var responseCode = 404;
var message = getMessage(responseCode);
print(message);
}
String getMessage(int responseCode) {
if (responseCode == 404) {
return 'Not found';
} else if (responseCode >= 500) {
return 'Critical';
}
return 'Unknown';
}
ဒါကို switch နဲ့ အခုလိုမျိုး ပြောင်းရေးလို့ ရပါတယ်။
String getMessage(int responseCode) {
switch (responseCode) {
case 404:
return 'Not found!';
case 500:
return 'Critical';
default:
return 'Unknown';
}
}ဒီမှာ တခုရှိတာက switch statement တွေသုံးမယ်ဆို တူ မတူကိုပဲ အဓိကထားပြီး စစ်လို့ရတာပါ။ အပေါ်မှာ ပေးထားတဲ့ if-else နဲ့ switch statement တွေက တူသယောင်ရှိပေမယ့် တကယ်လို့ switch statement နဲ့ ရေးထားတဲ့ function ကို getMessage(520) ဆိုပြီးခေါ်လိုက်ရင် "Unknown" ဆိုပြီး return ပြန်ပေးမှာပဲ ဖြစ်ပါတယ်။ ဒါကို switch expression နဲ့ ဖြေရှင်းလို့ရပါတယ်။
String getMessage(int responseCode) {
return switch (responseCode) {
404 => 'Not Found',
>= 500 => 'Critical',
_ => 'Unknown',
};
}အပေါ်မှာပေးထားတဲ့ code က if-else နဲ့စစ်တာနဲ့ အတူတူပဲ ဖြစ်ပါတယ်။ ထင်သာမြင်သာရှိပြီး ပိုပြီး ရှင်းလင်းပါတယ်။
တကယ်လို့ ကျွန်တော်တို့ switch expression ထဲကို ပေးလိုက်တာက variable တခုထဲမဟုတ်ဘဲ တခုထက်ပိုပါတဲ့ Record, List, Map, Class တို့ဖြစ်နေရင်ရော ဘယ်လို လုပ်မလဲ?
final cityInfo = ('Yangon', 16.8, 96.0)အဲ့ဒါဆိုရင်တော့ pattern matching ကို အသုံးပြုပြီးတော့ စစ်သွားလို့ရပါတယ်။ Dart မှာ ဝင်လာမယ့် data နဲ့ structure ကို သိတယ်ဆို ဘယ်လို value ကိုပဲ ဖြစ််ဖြစ် pattern matching လုပ်ပြီး စစ်လို့ရပါတယ်။
void main() {
final yangon = ('Yangon', 16.8, 96.0);
final mandalay = ('Mandalay', 21.9, 96.0);
final naypyidaw = ('Naypyidaw', 19.7, 96.0);
print(getCityInfo(yangon));
print(getCityInfo(mandalay));
print(getCityInfo(naypyidaw));
}
String getCityInfo((String name, double lat, double long) city) {
return switch (city) {
('Yangon', _, _) => 'Yangon has a lot of career opportunities.',
('Mandalay', _, _) => 'Mandalay has rich cultural heriage.',
_ => "No info for this.",
};
}
// Output:
// Yangon has a lot of career opportunities.
// Mandalay has rich cultural heriage.
// No info for this.နောက်ထပ် ဥပမာတခုလောက် ထပ်ကြည့်ကြည့်ရအောင်ပါ။ Pattern matching မှာ value တခုထဲကို မဟုတ်ဘဲ တခုထက်ပိုတဲ့ value တွေကိုလဲ switch ကို အသုံးပြုပြီးတော့ စစ်လို့ရပါတယ်။
void main() {
print(getTrafficLightMessage(('red', 90)));
print(getTrafficLightMessage(('green', 5)));
print(getTrafficLightMessage(('yellow', 3)));
}
String getTrafficLightMessage((String color, int time) light) {
return switch (light) {
('red', var sec) when sec > 60 => 'Long red light - grab a coffee! ($sec seconds)',
('red', _) => 'STOP! Do not cross.',
('yellow', _) => 'CAUTION! Prepare to stop.',
('green', var sec) when sec < 10 => 'Hurry! Only $sec seconds left!',
('green', _) => 'GO! Safe to cross.',
_ => 'Unknown light state - stay alert!',
};
}
// Output:
// Long red light - grab a coffee! (90 seconds)
// Hurry! Only 5 seconds left!
// CAUTION! Prepare to stop.ဒီ ဥပမာမှာဆို color ရော time ကိုရောပါ စစ်သွားတာ တွေ့နိုင်ပါတယ်။ ဒီထဲမှာ var sec ဆိုတဲ့အသုံးအနှုန်းကို သတိထားမိပါလိမ့်မယ်။ ဒါကတော့ ဝင်လာတဲ့ value ကို variable အနေနဲ့ ပြန်ပြီး အသုံးချချင်တဲ့အခါ ရေးတဲ့ အရေးအသားပဲ ဖြစ်ပါတယ်။
List အတွက်ရော ဘယ်လို pattern matching လုပ်မလဲ ဆက်ကြည့်ရအောင်ပါ။
void main() {
print(analyzeList([1, 2, 3, 4]));
print(analyzeList([1]));
print(analyzeList([5, 10, 15, 20]));
}
String analyzeList(List<int> numbers) {
return switch (numbers) {
// Empty list
[] => 'Empty list',
// Single element
[var single] => 'Only one number: $single',
// Exact pattern
[1, 2, 3] => 'Exactly [1, 2, 3]',
// First element pattern
[1, ...] => 'Starts with 1',
// Rest pattern
[var first, var second, ...var rest] =>
'First: $first, Second: $second, Rest: $rest',
};
}
// Output:
// Starts with 1
// Only one number: 1
// First: 5, Second: 10, Rest: [15, 20]List နဲ့ pattern matching လုပ်တဲ့အခါ ပါတဲ့ value တခုချင်းစီနဲ့ပါ လုပ်သွားလို့ရပါတယ်။ ဒီမှာဆိုရင်တော့ pattern တဆင့်ပြီး တဆင့် စစ်သွားပေးတာပါ။ ဒီတော့ pattern matching လုပ်တဲ့ order ကလဲ အရေးကြီးပါတယ်။ Order လွဲသွားခဲ့ရင်တော့ match လုပ်တဲ့ဟာလဲ လွဲသွားနိုင်တဲ့အတွက် သတိထားဖို့တော့ လိုပါတယ်။
void main() {
print(analyzeList([1, 2, 3, 4]));
print(analyzeList([1]));
print(analyzeList([5, 10, 15, 20]));
}
String analyzeList(List<int> numbers) {
return switch (numbers) {
// Rest pattern
[var first, var second, ...var rest] =>
'First: $first, Second: $second, Rest: $rest',
// Empty list
[] => 'Empty list',
// Single element
[var single] => 'Only one number: $single',
// Exact pattern
[1, 2, 3] => 'Exactly [1, 2, 3]',
// First element pattern
[1, ...] => 'Starts with 1',
};
}
// Output:
// First: 1, Second: 2, Rest: [3, 4]
// Only one number: 1
// First: 5, Second: 10, Rest: [15, 20]Map data type ဆိုရင်ရော ဘယ်လိုမျိုး pattern matching လုပ်လို့ရမလဲဆိုတာ ဆက်ကြည့်ကြရအောင်ပါ။
void main() {
print(checkConfig({'debug': true, 'apiKey': 'abc123'}));
print(checkConfig({'debug': false}));
print(checkConfig({'debug': false, 'apiKey': 'abc123'}));
print(checkConfig({'debug': false, 'version': 1, 'apiKey': 'abc123'}));
}
String checkConfig(Map<String, dynamic> config) {
return switch (config) {
{'debug': true, 'apiKey': var key} => 'Debug mode with key: $key',
{'debug': false, 'version': var v, 'apiKey': _} => 'Production v$v',
{'debug': _} when !config.containsKey('apiKey') => 'Error: Missing API key',
_ => 'Invalid config',
};
}
// Output:
// Debug mode with key: abc123
// Error: Missing API key
// Invalid config
// Production v1ဒီမှာတော့ Map data type ဖြစ်တဲ့အတွက် ပါလာတဲ့ key တွေနဲ့ သူတို့ရဲ့ value တွေကို အပေါ်မှာ ပြထားသလိုမျိုး စစ်သွားလို့ ရပါတယ်။
Class/Object တွေနဲ့ pattern match လုပ်တာကိုတော့ Object Oriented Programming (OOP) ပိုင်းတွေ ရောက်တဲ့အခါ ပြောပေးသွားပါမယ်။
ဒါဆိုရင်တော့ pattern matching နဲ့ပတ်သက်ပြီး ရှင်းလင်းပြီ ထင်ပါတယ်။
ဒီနေ့ Day 4 အတွက်ကတော့ ဒီလောက်ပဲ ဖြစ်ပါတယ်။ အဆုံးထိ ဖတ်ပေးတဲ့အတွက် အများကြီး ကျေးဇူးတင်ပါတယ်။ နားမလည်တာတွေ အဆင်မပြေတာတွေ ရှိခဲ့ရင်လဲ အောက်မှာပေးထားတဲ့ discord server ထဲမှာ လာရောက်ဆွေးနွေးနိုင်ပါတယ်။ နောက်နေ့တွေမှာလဲ ဆက်လက်ပြီး sharing လုပ်သွားပေးသွားမှာ ဖြစ်တဲ့အတွက် subscribe လုပ်ထားဖို့ ဖိတ်ခေါ်ပါတယ်။
- Youtube: https://www.youtube.com/@arkarmintun
- Newsletter: https://arkar.dev/
- Discord: https://discord.gg/3xUJ6k6dkH