The Truth Will Set You Free
What's true? What's false? Why in the world is a cartooned programming book asking you existential questions?
Well in Ruby what's truthy and what's falsy are pretty straightforward, if it's not nil
or false
it's truthy. True and False together make up this new concept called a Boolean.
Docs
- https://ruby-doc.org/core/TrueClass.html
- https://ruby-doc.org/core/FalseClass.html
- https://ruby-doc.org/core/NilClass.html
Tabling the Discussion
In fancy Computer math, we draw out these things called Truth tables. You could think of them almost like Punnet squares, those things where you take something on the top and something on the side and see what happens if you smush 'em together in the middle.
For our squares we're going to see what happens when you combine true
and false
a few different ways:
AND: | true | false |
---|---|---|
true | true | false |
false | false | false |
When something is true and true, it's true. Same with the rest of the combinations.
OR: | true | false |
---|---|---|
true | true | true |
false | true | false |
Or can be shown the same way, but notice that we only need one side to be truthy to get true.
To start with we’ll take a look at and (&&
) and or (||
)
2.4.2 :001 > true && true
=> true
2.4.2 :002 > true || false
=> true
2.4.2 :003 > true && false
=> false
2.4.2 :004 > false || false
=> false
2.4.2 :005 > false && false
=> false
What we’re saying is for or we need one side of it to be true, and for and we need both. There are a few more, but this should get us started well for now.
Keep in mind that everything in Ruby is truthy except for false
and nil
. That means if you put a variable or anything else with &&
or ||
it doesn’t have to be explicitly true or false. It just needs to quack like a duck to be treated like a duck.
Just remember that truthy
and true
aren't the same, and we can test that with ==
which is checking if things are equal:
2.4.2 :006 > true == 1
=> false
2.4.2 :007 > false == nil
=> false
2.4.2 :008 > true == true
=> true
2.4.2 :009 > false == false
=> true
A Greater Truth
( Pic - 7 8 9 joke )
Remember Numbers? We can see if they're equal too, but that's no fun. What if we want to know the greater truths?
2.4.2 :010 > 6 < 7
=> true
Why was 6
afraid of 7
? Because 7
8
9
of course, but why would it? Well we're supposed to get 3
square meals a day!
2.4.2 :011 > 3**2 == 9
=> true
In Ruby we can check inequalities just as easily, so things like greater than, less than, or other operators work here too:
2.4.2 :012 > 6 < 7
=> true
2.4.2 :013 > 7 > 6
=> true
2.4.2 :014 > 6 >= 6
=> true
and so on and so forth.
English Operators
Weren’t there english operators? Can’t we just use and
and or
like normal civil people? Well...
...it turns out not quite. For most cases they’ll look and act the exact same, except that one has much different precedence than the other.
Think PEMDAS or Order of Operations, Ruby operators work the same way. The english operators are much higher priority than others.
In the days of old, the mighty Perl programmers would use such operators for flow control:
some_condition_met or exit
some_condition_met and return 'We made it!'
Reads nice, but some Ruby types will throw a fit if you use it. That’s not a fight I’m keen to get into, but in general you should avoid the english versions of and
and or
.
Ah! Do be aware Programmers love to fight about this stuff. Right scary it is, but not really relevant to learning is it?
Asking Questions
Remember that question mark back in the Numbers section on the end of odd?
? In Ruby we can make methods ending with a question mark, so it’s kinda like we’re asking something a question.
Am I odd? Why yes, yes I am, and this book is a glaring indictment of that one.
We call these predicate methods, though you can probably get away with calling them question methods.
Something might be empty, so we ask it: "".empty?
Perhaps we don't remember what that variable was, we could up and ask it if it's a Number: 8.is_a?(Integer)
Just remember, whenever you see something ending with a question mark in Ruby, it typically means that it's asking a question and it's going to return a Boolean value. If it doesn't, someone's doing something particularly bad.
What If?
How do we go and use this magical concept of truth to do things? We use if
!
If my car doesn't have gas then I want to go and fix that, otherwise I'm fine and I can probably ignore it for a while more. Perhaps a wiser idea would be to check that you have over a quarter tank instead, never know when toeing the line costs ya a foot.
So let’s say that in code right quick:
if car.fuel < 0.25
car.refill
else
car.drive
end
If the car’s fuel is less than 25%, we refill it, else we keep driving.
Where'd we get the car
? I think from something called LISP
, such a Little Schemer it is. Jokes aside, car
is just an example object for us to play with for now.
Like our truth table above, we can use more than a few conditions in there:
if car.fuel < 0.25 || gas_is_a_good_deal
car.refill
else
car.drive
end
You could even stick your if after what you want to do:
car.refill if car.fuel < 0.25
We call that one a suffix conditional, and for shorter ones it can read a bit more cleanly at that.
There's another way to make a conditional called a ternary operator. It's another use for the question mark in Ruby, and it looks like this:
condition ? if_true : if_false
So what's that mean? Well you might recognize it a bit more if we wrote it out as an if / else
instead:
if condition
if_true
else
if_false
end
So all a ternary is is a bit of shorthand. That said, one needs to be careful about shoving too many things on one line. It can get awful crowded awful quick if you don't.
If you want to remember it a bit easier, think of it as Elvis hair! ?:
See, even got that swirl.
Just in Case
( Pic - Lemur with case )
This one’s not a hard case to crack, it’s the case statement!
Find yourself writing something like this in Ruby?
if text == 'string'
...
elsif text == 'other_string'
...
elsif text == 'only_one_more_i_promise'
...
else
'Maybe I lied'
end
That seems like an awful lot of text ==
in there, and I don’t know about all of you but I take personal offense to typing much more than I have to. That’s where case comes in! Let’s take a look at the same code using a case instead:
case text
when 'string'
...
when 'other_string'
...
when 'only_one_more_i_promise'
...
else
'Maybe I lied'
end
Now that looks better. Thing about case though, it has a lot of fun tricks, and The Professor is just dying to teach us a few.
Case statements use the ===
operator in the background. Normally that’s the same as ==
, but for some types it’s overridden to do fun things.
This article explains a lot of what goes on with ===
, though be warned that there is indeed black magic to follow: https://medium.com/rubyinside/triple-equals-black-magic-d934936a6379