Making decisions
In the previous lesson we went from some fixed functions to a flexible one that accepts an argument.
Before:
function greetSally() {
console.log("Hello Sally Brown");
}
function greetCharlie() {
console.log("Hello Charlie Brown");
}
greetSally();
greetCharlie();
And after:
function greet(person) {
console.log("Hello", person);
}
greet('Sally Brown');
greet('Charlie Brown');
Passing more parameters to a function
Now we want to enhance our greet function to adjust the greeting to the time of the day, let's say "Good morning" it it's not noon yet, and "Good afternoon" after that.
Since functions wear no watches, it's hard for them the guess the hour. We have to tell them, any idea how? Exactly, we need another parameter!
In order to keep things simple, we'll assume that the time is expressed in integer numbers, no minutes nor seconds. We'll also greet just Charlie for a moment, sorry Sally!
function greet(person, time) { console.log("Good morning", person); } greet('Charlie Brown', 9); greet('Charlie Brown', 15);
Toggle Console Output
- 'Good morning Charlie Brown'
- 'Good morning Charlie Brown'
See how we adjusted the greeting to be Good morning and not Hello anymore. We are calling the function twice, first with a morning hour, then with an afternoon one. We still see no difference in behavior, because we haven't changed much inside the function!
Our first conditional
Let's go straight to business:
function greet(person, time) { if (time > 12) { console.log("Good afternoon", person); } else { console.log("Good morning", person); } } greet('Charlie Brown', 9); greet('Charlie Brown', 15);
Toggle Console Output
- 'Good morning Charlie Brown'
- 'Good afternoon Charlie Brown'
Bunch of stranger symbols and keywords we salute you! Don't panic and look at the results: they do what we wanted!
First let's observe how we have two console.log statements in the function body, but just one per call gets executed. That means that there should be some decision mechanism that chooses which one to run. Such mechanism is called an if / else statement:
if (time > 12) {
console.log("Good afternoon", person);
} else {
console.log("Good morning", person);
}
More generally we have:
if ( some condition ) {
// if block:
// stuff that gets executed if the condition is met
} else {
// else block:
// stuff that gets executed if the condition is not met
}
A block statement is used to group zero or more statements. The block is delimited by a pair of curly braces and contains a list of zero or more statements and declarations.
The two blocks are mutually exclusive: if the condition is met, just the if block We have to rigorously define what "some condition" is, and how the machine checks if it is met. We'll do it in at the end of this cycle of lessons.
The > symbol is called the greater than operator. It behaves similarly to the other operators you already know, like the plus or the multiplication operators: they all take two numbers and associate them with something else.
console.log('2 + 3', 2 + 3); console.log('2 * 3', 2 * 3); console.log('2 > 3', 2 > 3);
Toggle Console Output
- '2 + 3'5
- '2 * 3'6
- '2 > 3'false
As you can imagine, there is also a lesser than operator (<):
console.log('2 > 3', 2 > 3); console.log('2 < 3', 2 < 3);
Toggle Console Output
- '2 > 3'false
- '2 < 3'true
True and false
Wait wait, what are those true and false things now? They are called boolean values, we'll cover them in detail soon. For now think that they are answers to a yes or no question.
As you can imagine there are also the equals operator, the lesser or equals to operator and the greater or equals to operator. We'll deal with the first one in a moment in a slightly different context.
We introduced a lot of notation and concepts. Covering all of them in detail would make you lose focus from the main story, that is to enhance our greet function. Let's reinforce what we have seen so far by reinspecting the code we have written so far. For instance we named the parameters person and time. Remember that your can rename them!
function greet(name, hour) { if (hour > 12) { console.log("Good afternoon", name); } else { console.log("Good morning", name); } } greet('Charlie Brown', 9); greet('Charlie Brown', 15);
Toggle Console Output
- 'Good morning Charlie Brown'
- 'Good afternoon Charlie Brown'
The output stays the same. Once again it's up to your how you name the params. Let's greet Sally and some Van Pelts as well:
function greet(name, hour) { if (hour > 12) { console.log("Good afternoon", name); } else { console.log("Good morning", name); } } greet('Linus Van Pelt', 15); greet('Sally Brown', 17); greet('Lucy Van Pelt', 8); greet('Lucy Van Pelt', 19);
Toggle Console Output
- 'Good afternoon Linus Van Pelt'
- 'Good afternoon Sally Brown'
- 'Good morning Lucy Van Pelt'
- 'Good afternoon Lucy Van Pelt'
See how the output varies depending on the input. That's programming, an input and output mantra, just like breathing. That's new age sloganism at its finest! Get familiar with this aspects and you'll be ace. Do yu want to know about how to fine tune our function further so it can say good evening as well? Stay tuned!
Comparing strings
We compared numbers to see if the passed time was later than noon. Let's now write a suggestPlans function that accepts a name and weather parameter, and suggest us what to do depending on the outdoor conditions. It should greet the given name - just with a simple hello this time - and tell us to have a walk if it's sunny, and to drink something warm home if it's raining. If the given weather is neither sunny nor rainy, it should tell us that it cannot be of much help.
function suggestPlans(name, weather) { console.log('Hello', name); if (weather == 'sunny') { console.log("Let's have a walk in a park and chill there!"); } else if (weather == 'rainy') { console.log("That's a bummer. Let's fix ourselves a cuppa and spin some good record!"); } else { console.log('I am out of ideas sorry!'); } } suggestPlans('Charlie', 'sunny'); suggestPlans('Sally', 'rainy'); suggestPlans('Snoopy', 'windy');
Toggle Console Output
- 'Hello Charlie'
- "Let's have a walk in a park and chill there!"
- 'Hello Sally'
- "That's a bummer. Let's fix ourselves a cuppa and spin some good record!"
- 'Hello Snoopy'
- "I am out of ideas sorry!"
What can we say about the suggestPlans function?
- it depends on two parameters,
nameandweather; - it has three possible behaviors: one if the weather is sunny, one if it's rainy, a further one otherwise;
- it has some shared feature that happens in all cases, i.e. the initial
Hello {name}log; - it has a chain of
if / else if / elseblocks; - the condition of the
ifandelse ifblocks is to compare theweatherparameter first with the'sunny'string, then with'rainy'one.
The equality operator
The comparison is responsibility of the equality operator (==), depicted with two (!) equals. Why two equals and not one? Because the single equals is another operator, whose purpose is going to be discussed in two lessons from now.
Let's observe how the operator behaves:
console.log('cat' == 'dog'); console.log('cat' == 'Cat'); console.log('cat' == 'cat');
Toggle Console Output
- false
- false
- true
- comparing two completely different strings evaluates to
false; - comparing two strings that differ just by case evaluates to
false; - comparing two strings that match in content and case evaluates to
true.
Boolean values again! Comparing two string does certainly not leave room for a third option, either they match or not. Tertium non datur.
Coming back to the suggestPlans function, the comparison is between the value of the parameter and the fixed strings inside the function body:
if (weather == 'sunny') {
console.log("Let's have a walk in a park and chill there!");
} else if (weather == 'rainy') {
console.log("That's a bummer. Let's fix ourselves a cuppa and spin some good record!");
} else {
console.log('I am out of ideas sorry!');
}
The operator first checks if weather in the current call holds 'sunny' as value. If it's not the case proceeds to the else if block and does the same against 'winter'. The machine has no idea about what those strings mean, it just checks if they have the same value.
Dealing with logic in programming can be convoluted at first. We'll see a lot of examples so you can familiarize with the syntax. For now focus as much as possible on the idea that different inputs lead to different outputs depending on how they match the internal function decisions.
if, else if, else
In the previous example we have seen just an if / else structure, while now we introduced another decision thanks to the else if. More generally:
if ( condition ) {
// things that happen if condition is met
} else if ( anotherCondition ) {
// things that happen if the previous condition is not met
// and if anotherCondition is met
} else {
// things that happen if none of the above conditions are met
}
One could have an arbitrary number of else if ( ... ) blocks:
if ( condition ) { ... }
else if ( anotherCondition ) { ... }
else if ( yetAnotherCondition) { ... }
...
else { ... }
But before you get carried away, we'll see how this is not particularly good code. We want our function to be as specialized as possible, without the need of taking too many decisions. We'll discuss the strategies to avoid the common pitfalls.
Isolated if blocks
An if block should not compulsory be followed by an else block:
const daysOfLearning = 9; console.log("Today I will study some JavaScript."); if (daysOfLearning > 7) { console.log("It's more than a week that I am studying already!"); }
Toggle Console Output
- "Today I will study some JavaScript."
- "It's more than a week that I am studying already!"
We just wanted to append a second log after the first one, without deciding an alternative message to write. The less if / else we use in our code, the better actually! Less decisions to take, fewer scenarios to check.
The strategy for writing code that works
There are two main things that cause problems to developers: knowing how to do something, and knowing what to do. You can ask for help for the former, but it's much harder to clarify the latter.
Let's pretend that we haven't gone through the greet function story yet, and we get the following requirement / exercise:
Write a function called
greetthat takes two parameters - a person's name and the time of the day, and logsGood morning {the name}if the time is lesser than 12, andGood afternoon {the name}otherwise.
You want to have a solid strategy in tacking the problem. I strongly suggest to do the following:
- write the function signature first, without anything in the function body;
- write some function calls below the function, with different arguments covering all the expected cases;
- comment the calls with the expected out;
- review what you have done so far, sit back and relax.
function greet(person, time) {
// NOTHING HERE
}
// should log 'Good morning Charlie Brown'
greet('Charlie Brown', 9);
// should log 'Good afternoon Charlie Brown'
greet('Charlie Brown', 15);
This generates no output, it's an empty function after all. But I already know what the function should do. Now I can write the function body and fulfill the how.
Conclusion
I've met various students and fellow developers that start frantically typing like headless chickens before knowing what they are supposed to do. Well I haven't actually seen headless chickens approach a computer but I guess that's what they would do. You don't have to rush! Programming is about functions, and functions are about their input and their output. If you don't put most of your attention on those two aspects, it's worthless to invest energy in what happens inside them!