How could I use a switch statement for this lesson?

You won’t get any argument from me. The above is just a demo, not a recommendation.

To drive home my point about functions eclipsing everything else, this is all one big expression, not a single statement (other than the expression itself)

// entry point / main
(default_ => (switch_ => (life_cycle => (
  console.log(life_cycle(-1)),
  console.log(life_cycle(0)),
  console.log(life_cycle(3)),
  console.log(life_cycle(13)),
  console.log(life_cycle(20)),
  console.log(life_cycle(65)),
  console.log(life_cycle(75)))

// life_cycle
)(switch_(switch_,
  [ [age => age < 0 || age > 140, () => "This is not a valid age."]
  , [age => age < 3,  () => 'baby']
  , [age => age < 13, () => 'child']
  , [age => age < 20, () => 'teen']
  , [age => age < 65, () => 'adult']
  , [age => age < 75, () => 'senior']
  , [default_,        () => 'elderly']
  ]))

// switch_
)((switch_, cases) => (x, i=0) => (
  (([condition, result]) =>
    condition(x)
    && result()
    || switch_(switch_, cases)(x, i+1)
  )(cases[i]))

// default_
))(() => true)

Hello Roy.

Would you mind to explain to me what the following line of code that you wrote does?

case age < 0: age = 141;

Thanks in advance.

No real magic, just short-circuiting to the default case by setting age to fail all the test cases. It seemed less cluttered than,

case age < 0 or age > 140: return "This is not a valid age."

which effectively eliminates the default case. The other way just seemed a better fit, and it’s neater.

1 Like

Hello.

let age = -1;

switch (true) {
  case age < 0: age = 141;
  case age < 3: console.log('baby'); break;
  case age < 13: console.log('child'); break;
  case age < 20: console.log('teen'); break;
  case age < 65: console.log('adult'); break;
  case age < 75: console.log('senior'); break;
  case age < 141: console.log('elderly'); break;
  default: console.log("This is not a valid age.");
}

I tried out the code you posted using the switch statement, but when age variable is assigned a value of -1, console still prints out ‘baby’. If I print out the value of age variable after the switch statement, it prints 141, so the value was reassigned but short-circuiting to the default case does not work.

Why is the reassigned value not recognized? I am still a beginner, would it be possible for you to provide assistance?

Thank you in advance.

We’ve just discovered the JS does not support reassignment of the case expression inside the switch. That’s what I get for not fully testing. Thanks for pointing that out.

1 Like

Hello, @dev3973791745, and welcome to the forums.

You’ve hit upon a common misconception of how switch...case works. Once the switch expression is evaluated, control is passed to the first truthy case. Then control continues to flow until it is altered again. Subsequent cases are not evaluated.
case age < 3: is like a street sign. It’s a label. Once switch decides which label to pass control to, the remaining labels are ignored. Your code assigns 141 to age, and then console.log('baby') is executed followed by break which sends control to whatever follows the closing } for the switch.

Try removing the break; statements following each case, and see what the output is.

For example:

let age = -1;

switch (true) {
  case age < 0: age = 141;
  case age < 3: console.log(age, 'baby'); age += 10;
  case age < 13: console.log(age, 'child'); age += 10;
  case age < 20: console.log(age, 'teen'); age += 10;
  case age < 65: console.log(age, 'adult'); age += 10;
  case age < 75: console.log(age, 'senior'); age += 10;
  case age < 141: console.log(age, 'elderly'); age += 10;
  default: console.log("This is not a valid age.");
}

console.log("I'm done with your switch.")

Output:

141 ‘baby’
151 ‘child’
161 ‘teen’
171 ‘adult’
181 ‘senior’
191 ‘elderly’
This is not a valid age.
I’m done with your switch.

Throw a break in:

let age = -1;

switch (true) {
  case age < 0: age = 141;
  case age < 3: console.log(age, 'baby'); age += 10;
  case age < 13: console.log(age, 'child'); age += 10; break;
  case age < 20: console.log(age, 'teen'); age += 10;
  case age < 65: console.log(age, 'adult'); age += 10;
  case age < 75: console.log(age, 'senior'); age += 10;
  case age < 141: console.log(age, 'elderly'); age += 10;
  default: console.log("This is not a valid age.");
}

console.log("I'm done with your switch.")

Output:

141 ‘baby’
151 ‘child’
I’m done with your switch.

2 Likes

Was it Mark Twain who wrote, “First get your facts straight, then distort them at your leisure.”?

2 Likes

One advantage of a switch statement over functions? Efficiency.

Switch statements aren’t so bad, they can be 100 times more readable than a chain of if else’s or an if statement with lots of ors.

They are typically faster than lots of if else’s and are easier for compiler/JIT optimisations. They can have a time complexity of O(1) when comparing cars (don’t count on that in JavaScript though).

They aren’t too bad to maintain and aren’t complex to create.

Using the ability to fall through can sometimes be a nice solution to a problem, despite what to anti-fall through anti-goto brigade say.

Thank you for being here and answering all those questions from everyone. I will keep it in mind going forward.

Thank you for your post, this explanation helped clear some things up.
This is kinda off-topic, but do you know of a good resource that explains definitions of important programming terms like statement, expression, control flow etc. that a novice could easily grasp? I am not a native english speaker and I sometimes have trouble understanding things because I don’t know what exactly these words represent in programming terms.

Thank you again.

1 Like

Not really, unfortunately. Google is as good a resource as any. If you add a term like ‘computer science’ to a search, you will ideally get programming related results listed first. Something like:

expression (computer science)

1 Like

No problem. I found some good websites using your suggestion. They will suffice.

Thanks again for the help.

1 Like

I’ve been pulling my hair out over this for the better part of an hour, thank you so much for clearing it up!!

1 Like

Amazing! Thank you @mtf

1 Like

In the above code, how is the (age) variable passed into the switch statement?

I put it into a function lifePhase(age), which behaves as expected, except for negative numbers, it always returns baby, like so:

console.log(lifePhase(-6)) //prints baby
console.log(lifePhase(-35)) //also prints baby

Why did you only use {} for the first return statement, and why isn’t this throwing a syntax error?
I’d write it like this:

function life_cycle(age) {
  if (age < 0 || age > 140) {
    return "This is not a valid age.";
  }
  if (age < 3) {
    return 'baby';
  }
  if (age < 13) {
    return 'child';
  }
 //and so on
}

That code will not work as expected since it ignores the assignment in the switch so age does not get changed, as one had hoped. The first case needs to be changed to,

 case age < 0:  return "This is not a valid age."

age is a variable in parent scope so is accessible in the switch block.

The validation could be done before the switch…

if (age < 0 || age > 140) return "This is not a valid age."
switch(age) {
case age < 3: return 'baby';
...
case age < 75: return 'senior';
default: return 'elderly'
}
1 Like

I thought that if I used only less than a certain number, for example age < 65, that could mean that any of the following fits in ie, adult, teen or even child fits in but when I use ranges such as if (age >=20 && age <= 64), that gets assigned or returns only adults.

Here is my code that works perfectly well for me but I did not see it here as one of the examples given and I began to wonder if I have done something wrong that worked all the same.

const lifePhase = (age) => {
if (age >= 0 && age <= 3) {
return ‘baby’;
}else {
if (age >= 4 && age <=12) {
return ‘child’;
}else {
if (age >= 13 && age <= 19) {
return ‘teen’;
}else {
if (age >= 20 && age <= 64) {
return ‘adult’;
}else {
if (age >= 65 && age <= 140) {
return ‘senior citizen’;
}else {
if (age < 0 || age > 140) {
return ‘This is not a valid age’
}
}
}
}
}
}
}

console.log(lifePhase(5)) //should print ‘child’
console.log(lifePhase(25)) //should print ‘child’
console.log(lifePhase(141)) //should print ‘child’
console.log(lifePhase(78)) //should print ‘child’
console.log(lifePhase(18)) //should print ‘child’
console.log(lifePhase(2)) //should print ‘child’
console.log(lifePhase(-1)) //should print ‘child’

If we place that condition at the top of the function then it eliminates the invalid ages, right off. Then we know the age is valid so we can start from lowest to highest to work our way up to ‘senior’.

if (a < 4) {
    // baby
} else
if (age < 13) {
    // child
} else
if (age < 20) {
    // teen
} else
if (age < 65) {
    // adult
} else {
    // senior
}

This results in there being no gaps if age happens to be a float.