FrostyCat
Redemption Seeker
How NOT to use switch
GM Version: N/A
Target Platform: All
Download: N/A
Links: N/A
Summary: A summary of common novice abuses of switch with corresponding alternatives.
Introduction
Some novices learning switch blocks fall into the trap of trying to use it everywhere and inventing imaginary syntax for it. This tutorial lists several common abuses and the corresponding correct code.
Misguided belief #1: "switch automatically plugs arguments into functions"
WRONG:
RIGHT:
Misguided belief #2: "switch automatically makes expressions out of fragments"
WRONG:
RIGHT:
Improved:
Misguided belief #3: "switch accepts ranges as cases"
WRONG:
WRONG:
WRONG:
RIGHT:
Improved (assuming that score is not negative):
RIGHT:
Note: This form can only be used when the ranges are equally spaced.
Misguided belief #4: "switch goes to the first true case"
WRONG:
RIGHT:
Improved:
WRONG:
RIGHT:
Misguided belief #5: "switch cases are combined using && and ||" (Also see: How NOT to use && and ||)
WRONG:
WRONG:
RIGHT:
Misguided belief #6: "switch can multitask with , or &&"
WRONG:
WRONG:
RIGHT:
RIGHT:
Note: string() is unnecessary when the values to compare are already strings. Make sure that the separator cannot appear in either component.
RIGHT:
Note: This form can only be used with integer values. The multiplier(s) should be big enough to make each combined value distinct.
RIGHT:
Note: This form can only be used when all case actions vary by a single constant value, and the cases are based on two integer values starting from 0.
What can be converted to switch blocks and what can't
switch blocks are not universal silver bullets, stop treating them like one. Use switch only when you are matching an expression against a discrete set of possible values using == only (must be constant in GMS 1.x and above), optionally plus a catch-all case.
In other words, only code in the following if-else ladder form have an equivalent switch block (final else optional):
Any code that cannot fit this form should not be written using switch blocks.
Checking for switch abuse
To check a switch block for abuse, convert it back to its equivalent if-else ladder form above. If it doesn't make sense, it's wrong.
Example 1: Is this valid?
Mapping it back to if-elseif form gives:
This is valid code, and so is the original.
Example 2: Is this valid?
Mapping it back to if-else form gives:
The first line clearly doesn't make sense, so the original is wrong. The right thing to do is proper if-else laddering.
Updates:
GM Version: N/A
Target Platform: All
Download: N/A
Links: N/A
Summary: A summary of common novice abuses of switch with corresponding alternatives.
Introduction
Some novices learning switch blocks fall into the trap of trying to use it everywhere and inventing imaginary syntax for it. This tutorial lists several common abuses and the corresponding correct code.
Misguided belief #1: "switch automatically plugs arguments into functions"
WRONG:
Code:
switch (keyboard_check_pressed) {
case vk_up: y -= 5; break;
case vk_down: y += 5; break;
case vk_left: x -= 5; break;
case vk_right: x += 5; break;
}
Code:
if (keyboard_check_pressed(vk_up)) {
y -= 5;
}
else if (keyboard_check_pressed(vk_down)) {
y += 5;
}
else if (keyboard_check_pressed(vk_left)) {
x -= 5;
}
else if (keyboard_check_pressed(vk_right)) {
x += 5;
}
WRONG:
Code:
switch (score) {
case <100: show_message("Below average"); break;
case =100: show_message("Average"); break;
case >100: show_message("Above average"); break;
}
Code:
if (score < 100) {
show_message("Below average");
}
else if (score == 100) {
show_message("Average");
}
else if (score > 100) {
show_message("Above average");
}
Code:
if (score < 100) {
show_message("Below average");
}
else if (score == 100) {
show_message("Average");
}
else {
show_message("Above average");
}
WRONG:
Code:
switch (score) {
case 0-99: show_message("You suck"); break;
case 100-199: show_message("Not bad"); break;
case 200-299: show_message("Nice"); break;
default: show_message("You rock"); break;
}
Code:
switch (score) {
case 0 <= score < 100: show_message("You suck"); break;
case 100 <= score < 200: show_message("Not bad"); break;
case 200 <= score < 300: show_message("Nice"); break;
default: show_message("You rock"); break;
}
Code:
switch (score) {
case 0 <= score && score < 100: show_message("You suck"); break;
case 100 <= score && score < 200: show_message("Not bad"); break;
case 200 <= score && score < 300: show_message("Nice"); break;
default: show_message("You rock"); break;
}
Code:
if (0 <= score && score < 100) {
show_message("You suck");
}
else if (100 <= score && score < 200) {
show_message("Not bad");
}
else if (200 <= score && score < 300) {
show_message("Nice");
}
else {
show_message("You rock");
}
Code:
if (score < 100) {
show_message("You suck");
}
else if (score < 200) {
show_message("Not bad");
}
else if (score < 300) {
show_message("Nice");
}
else {
show_message("You rock");
}
Code:
switch (score div 100) {
case 0: show_message("You suck"); break;
case 1: show_message("Not bad"); break;
case 2: show_message("Nice"); break;
default: show_message("You rock"); break;
}
Misguided belief #4: "switch goes to the first true case"
WRONG:
Code:
switch (name) {
case string_length(name)<6: show_message("Short name"); break;
case string_length(name)=6: show_message("Six-lettered name"); break;
case string_length(name)>6: show_message("Long name"); break;
}
Code:
if (string_length(name) < 6) {
show_message("Short name");
}
else if (string_length(name) == 6) {
show_message("Six-lettered name");
}
else {
show_message("Long name");
}
Code:
var name_length = string_length(name);
if (name_length < 6) {
show_message("Short name");
}
else if (name_length == 6) {
show_message("Six-lettered name");
}
else {
show_message("Long name");
}
Code:
switch (irandom(2)) {
case irandom(2)=0: show_message("Zero"); break;
case irandom(2)=1: show_message("One"); break;
case irandom(2)=2: show_message("Two"); break;
}
Code:
switch (irandom(2)) {
case 0: show_message("Zero"); break;
case 1: show_message("One"); break;
case 2: show_message("Two"); break;
}
WRONG:
Code:
switch (value) {
case 3 && 5:
show_message("Three or five");
break;
}
Code:
switch (value) {
case 3 || 5:
show_message("Three or five");
break;
}
Code:
switch (value) {
case 3: case 5:
show_message("Three or five");
break;
}
WRONG:
Code:
switch (importance, urgency) {
case 0,0: show_message("Do at your leisure"); break;
case 0,1: show_message("Unimportant but should be done ASAP"); break;
case 0,2: show_message("Unimportant and must be done right now"); break;
case 1,0: show_message("Kind of important but can wait"); break;
case 1,1: show_message("Kind of important and should be done ASAP"); break;
case 1,2: show_message("Kind of important and must be done right now"); break;
case 2,0: show_message("Very important but can wait"); break;
case 2,1: show_message("Very important and should be done ASAP"); break;
case 2,2: show_message("Critical task"); break;
}
Code:
switch (importance && urgency) {
case 0&&0: show_message("Do at your leisure"); break;
case 0&&1: show_message("Unimportant but should be done ASAP"); break;
case 0&&2: show_message("Unimportant and must be done right now"); break;
case 1&&0: show_message("Kind of important but can wait"); break;
case 1&&1: show_message("Kind of important and should be done ASAP"); break;
case 1&&2: show_message("Kind of important and must be done right now"); break;
case 2&&0: show_message("Very important but can wait"); break;
case 2&&1: show_message("Very important and should be done ASAP"); break;
case 2&&2: show_message("Critical task"); break;
}
Code:
switch (importance) {
case 0:
switch (urgency) {
case 0: show_message("Do at your leisure"); break;
case 1: show_message("Unimportant but should be done ASAP"); break;
case 2: show_message("Unimportant and must be done right now"); break;
}
break;
case 1:
switch (urgency) {
case 0: show_message("Kind of important but can wait"); break;
case 1: show_message("Kind of important and should be done ASAP"); break;
case 2: show_message("Kind of important and must be done right now"); break;
}
break;
case 2:
switch (urgency) {
case 0: show_message("Very important but can wait"); break;
case 1: show_message("Very important and should be done ASAP"); break;
case 2: show_message("Critical task"); break;
}
break;
}
Code:
switch (string(importance) + "|" + string(urgency)) {
case "0|0": show_message("Do at your leisure"); break;
case "0|1": show_message("Unimportant but should be done ASAP"); break;
case "0|2": show_message("Unimportant and must be done right now"); break;
case "1|0": show_message("Kind of important but can wait"); break;
case "1|1": show_message("Kind of important and should be done ASAP"); break;
case "1|2": show_message("Kind of important and must be done right now"); break;
case "2|0": show_message("Very important but can wait"); break;
case "2|1": show_message("Very important and should be done ASAP"); break;
case "2|2": show_message("Critical task"); break;
}
RIGHT:
Code:
switch (importance*3+urgency) {
case 0: show_message("Do at your leisure"); break;
case 1: show_message("Unimportant but should be done ASAP"); break;
case 2: show_message("Unimportant and must be done right now"); break;
case 3: show_message("Kind of important but can wait"); break;
case 4: show_message("Kind of important and should be done ASAP"); break;
case 5: show_message("Kind of important and must be done right now"); break;
case 6: show_message("Very important but can wait"); break;
case 7: show_message("Very important and should be done ASAP"); break;
case 8: show_message("Critical task"); break;
}
RIGHT:
Code:
var messages;
messages[0,0] = "Do at your leisure";
messages[0,1] = "Unimportant but should be done ASAP";
messages[0,2] = "Unimportant and must be done right now";
messages[1,0] = "Kind of important but can wait";
messages[1,1] = "Kind of important and should be done ASAP";
messages[1,2] = "Kind of important and must be done right now";
messages[2,0] = "Very important but can wait";
messages[2,1] = "Very important and should be done ASAP";
messages[2,2] = "Critical task";
show_message(messages[importance, urgency]);
What can be converted to switch blocks and what can't
switch blocks are not universal silver bullets, stop treating them like one. Use switch only when you are matching an expression against a discrete set of possible values using == only (must be constant in GMS 1.x and above), optionally plus a catch-all case.
In other words, only code in the following if-else ladder form have an equivalent switch block (final else optional):
Code:
var value = expression;
if (value == constant1) {
//val1
}
else if (value == constant2) {
//val2
}
//...
else {
//default
}
Checking for switch abuse
To check a switch block for abuse, convert it back to its equivalent if-else ladder form above. If it doesn't make sense, it's wrong.
Example 1: Is this valid?
Code:
switch (state) {
case "walking": sprite_index = spr_walking; break;
case "sleeping": sprite_index = spr_sleeping; break;
case "fighting": sprite_index = spr_fighting; break;
default: sprite_index = spr_idle; break;
}
Code:
var value = state;
if (value == "walking") {
sprite_index = spr_walking;
}
else if (value == "sleeping") {
sprite_index = spr_sleeping;
}
else if (value == "fighting") {
sprite_index = spr_fighting;
}
else {
sprite_index = spr_idle;
}
Example 2: Is this valid?
Code:
switch (mouse_check_button) {
case mb_left: show_message("left"); break;
case mb_right: show_message("right"); break;
case mb_middle: show_message("middle"); break;
}
Code:
var value = mouse_check_button;
if (value == mb_left) {
show_message("left");
}
else if (value == mb_right) {
show_message("right");
}
else if (value == mb_middle) {
show_message("middle");
}
Code:
if (mouse_check_button(mb_left)) {
show_message("left");
}
else if (mouse_check_button(mb_right)) {
show_message("right");
}
else if (mouse_check_button(mb_middle)) {
show_message("middle");
}
Updates:
- 2018-12-17: Fix a typo in one of the examples.
- 2016-11-20: Changed example in Misguided Belief #1 as per Alice's suggestion.
- 2016-11-25: Adjusted example in Misguided Belief #3 to better demonstrate the div approach and closed-min-open-max ranges.
Last edited: