Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"},
{:visual, github: "brooklinjazz/visual"}
])
Upon completing this lesson, a student should be able to answer the following questions.
- What are booleans, and what information might they represent in a program?
- What are the boolean operators, and what do they do?
- What are strict vs non-strict boolean operators?
- What are
if
statements, and how are they useful in our programs?
Booleans (BOO-LEE-ANS) are true
and false
values in your code. They are often useful for
representing conditions and triggering actions in your program.
true
false
As part of programming, you'll often create branching paths. Essentially there are multiple things that could happen depending on certain conditions. We often call this control flow.
Let's take an example and say we have a program that controls a light.
Either we can tell the light to power on
or power off
. In this case, on
would be true
and off
would be false
.
flowchart LR
A[is_powered] --> true --> on
A[is_powered] --> false --> off
In the Elixir cell below, turn the power on in our light control program to see the light turn on! Replace false
with true
.
power = false
content = if power, do: "/images/on.png", else: "/images/off.png"
Kino.Image.new(File.read!(__DIR__ <> content), :png)
For more on booleans consider this video by Crash Course Computer Science.
YouTube.new("https://www.youtube.com/watch?v=gI-qXk7XojA")
Using the boolean operators and
, or
and not
we can compare and manipulate booleans.
Returns true
if left and right-hand side are true. Returns false
if either the left side and/or right side of the operator are false
.
flowchart LR
A[true] --> C
B[true] --> C
C[and] --> D[true]
true and true
true and false
false and true
false and false
Returns true
if either the left side or the right side of the operator are true
.
flowchart LR
A[false] --> C
B[true] --> C
C[or] --> D[true]
true or true
true or false
false or true
false or false
Flips false
-> true
and true
-> false
.
not true
not false
and
, or
, and not
are strict boolean operators, meaning they should only be used with booleans, otherwise they will raise an error.
1 and 1
Sometimes we want to make logical comparison using truthy and falsy values. nil
and false
are falsy values, and everything else is a truthy value.
We can use non-strict boolean operators &&
(and), ||
(or), and !
(not) to work with truthy and falsy values.
Returns the right-hand side value if the left-hand side value is truthy.
1 && 2
Returns the left-hand side value if it is falsy.
nil && 2
false && 2
Returns the first truthy value on either the left-hand side or the right-hand side.
2 || nil
1 || 2
nil || 2
Flips truthy -> false
and falsy -> true
.
!1
!nil
You might wonder why you shouldn't simply always use non-strict operators &&
, ||
, and !
since they also work with booleans.
true && true
false || true
!true
The primary reason is communication. We want our code to communicate to other developers, so it's useful to use and
, or
, and not
to communicate to other developers reading our code that we are working with boolean values.
Generally, prefer and
, or
, and not
with booleans, and use &&
, ||
, and !
with non-boolean values.
By comparing booleans, you can create branching paths in your code depending on certain conditions.
For example, let's say we're building a weather app. This app might send morning notifications to users to let them know that it's going to be a sunny day.
You might check that the user is subscribed, that it is morning, and that it is sunny. If all of these things are true, then we want to send a notification.
flowchart LR
A[is subscribed] --> and
B[is morning] --> and
C[is sunny] --> and
and --> true
true --> D[send notification]
and --> false
false --> E[don't send notification]
We can cleverly use boolean operators to write this logic. Try changing any of the true
values to false
and you'll see we no longer simulate sending a notification.
is_subscribed = true
is_morning = true
is_sunny = true
is_subscribed and is_morning and is_sunny && "send notification!"
Rather than rely on boolean operators entirely, it's more common to use specific control flow structures. For example, we can replicate the code above using if statements.
if is_subscribed and is_morning and is_sunny do
"send notification"
end
if
statements allow use to trigger some code when some condition is truthy. We often use if
statements in combination with else
statements to create two separate branching paths in our code.
For example, let's say we're creating a coin flip game. The user provides a guess
of :heads
or :tails
, and we have coin
flip of :heads
or :tails
.
flowchart LR
if/else --> c[coin == guess] --true--> w[You win!]
c --false--> l[You lose!]
Here's how we could write this in code. Try changing guess
to :heads
to win the coin flip game.
coin = :heads
guess = :tails
if coin == guess do
"You win!"
else
"You lose!"
end
Consider the following resource(s) to deepen your understanding of the topic.
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status
to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum
folder to commit your progress.
$ git add .
$ git commit -m "finish Booleans reading"
$ git push
We're proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.