A Little Bit of Logic

Let’s take another look at our first branching program, here. What if my wife came home, saw the program, tried it, and it didn’t tell her what a lovely name she had? I wouldn’t want her to flip out, so let’s rewrite it:

puts ​'Hello, what​'​s your name?'
name = gets.chomp
puts ​'Hello, '​ + name + ​'.'
if​ name == ​'Chris'
puts ​'What a lovely name!'
else
if​ name == ​'Katy'
puts ​'What a lovely name!'
end
end
<= Hello, what's your name?
=> Katy
<= Hello, Katy.
 What a lovely name!

Well, it works…but it isn’t a very pretty program. Why not? It just doesn’t feel right to me that the whole “Katy” chunk of code is not lined up with the “Chris” chunk of code. These are supposed to be totally equal and symmetrical options, yet one feels distinctly subordinate to the other. (In fact, this code would probably get me sleeping on the couch faster than just leaving her out of the program altogether.) This code just isn’t jiving with my mental model.

Fortunately, another Ruby construct can help: elsif. This code means the same thing as the last program but feels so much lovelier:

puts ​'Hello, what​'​s your name?'
name = gets.chomp
puts ​'Hello, '​ + name + ​'.'
if​ name == ​'Chris'
puts ​'What a lovely name!'
elsif​ name == ​'Katy'
puts ​'What a lovely name!'
end
<= Hello, what's your name?
=> Katy
<= Hello, Katy.
 What a lovely name!

This is a definite improvement, but something is still wrong. If I want the program to do the same thing when it gets Chris or Katy, then it should really do the same thing, as in execute the same code. Here we have two different lines of code doing the same thing. That’s not right. That’s not how I’m thinking about this.

More pragmatically, it’s just a bad idea to duplicate code anywhere. Remember the DRY rule? Don’t Repeat Yourself! For pragmatic reasons, for aesthetic reasons, or just because you’re lazy, don’t ever repeat yourself! Weed out duplication in code (or even design) whenever you see it. In our case, we repeated the line puts 'What a lovely name!'. What we’re trying to say is just, “If the name is Chris or Katy, do this.” Let’s just code it that way:

puts ​'Hello, what​'​s your name?'
name = gets.chomp
puts ​'Hello, '​ + name + ​'.'
if​ name == ​'Chris'​ || name == ​'Katy'
puts ​'What a lovely name!'
end
<= Hello, what's your name?
=> Katy
<= Hello, Katy.
 What a lovely name!

Nice. Much, much better. And it’s even shorter! I don’t know about you, but I’m excited. It’s almost the same as the original program! Bliss, I tell you…sparkly programming bliss!

To make it work, I used ||, which is how we say “or” in most programming languages.

At this point, you might be wondering why we couldn’t just say this:

...
if​ name == (​'Chris'​ || ​'Katy'​)
puts ​'What a lovely name!'
end

It makes sense in English, but you have to remember how staggeringly brilliant humans are compared to computers. The reason this makes sense in English is that humans are just fabulous at dealing with context. In this context, it’s clear to a human that “if your name is Chris or Katy” means “if your name is Chris or if it is Katy.” (I even used “it”—another triumph of human context handling.) But when your computer sees ('Chris' || 'Katy'), it’s not even looking at the name == code; before it gets there, it just tries to figure out whether one of 'Chris' or 'Katy' is true…because that’s what || does. But that doesn’t really make sense, so you have to be explicit and write the whole thing.

Anyway, that’s “or.” The other logical operators are && (“and”) and ! (“not”). Let’s see how they work:

i_am_chris = true
i_am_purple = false
i_like_beer = true
i_eat_rocks = false
puts i_am_chris && i_like_beer
puts i_like_beer && i_eat_rocks
puts i_am_purple && i_like_beer
puts i_am_purple && i_eat_rocks
puts
puts i_am_chris || i_like_beer
puts i_like_beer || i_eat_rocks
puts i_am_purple || i_like_beer
puts i_am_purple || i_eat_rocks
puts
puts !i_am_purple
puts !i_am_chris
true
false
false
false
true
true
true
false
true
false

The only one of these that might trick you is ||. In English, we often use “or” to mean “one or the other, but not both.” For example, your mom might say, ”For dessert, you can have pie or cake.” She did not mean you could have them both! A computer, on the other hand, uses || to mean “one or the other, or both.” (Another way of saying it is “at least one of these is true.”) This is why computers are more fun than moms. (Obviously I think my mom is far less likely to read this book than my wife is.)

Just to make sure everything is well cemented for you, let’s look at one more example before you go it alone. This will be a simulation of talking to my son, C, back when he was 2. (Just for background, when he talks about Ruby, Nono, and Emma, he is referring to his baby sister, Ruby, and his friends Giuliano and Emma. He manages to bring everyone he loves into every conversation he has. And yes, we did name our children after programming languages. And yes, my wife is the coolest woman ever.) So, without further ado, this is pretty much what happens whenever you ask C to do something:

while​ true
puts ​'What would you like to ask C to do?'
request = gets.chomp
puts ​'You say, "C, please '​ + request + ​'"'
puts ​'C​'​s response:'
puts ​'"C '​ + request + ​'."'
puts ​'"Papa '​ + request + ​', too."'
puts ​'"Mama '​ + request + ​', too."'
puts ​'"Ruby '​ + request + ​', too."'
puts ​'"Nono '​ + request + ​', too."'
puts ​'"Emma '​ + request + ​', too."'
puts
if​ request == ​'stop'
break
end
end

Let’s chat with C a bit.

<= What would you like to ask C to do?
=> eat
<= You say, "C, please eat"
 C’s response:
 "C eat."
 "Papa eat, too."
 "Mama eat, too."
 "Ruby eat, too."
 "Nono eat, too."
 "Emma eat, too."
 
 What would you like to ask C to do?
=> go potty
<= You say, "C, please go potty"
 C’s response:
 "C go potty."
 "Papa go potty, too."
 "Mama go potty, too."
 "Ruby go potty, too."
 "Nono go potty, too."
 "Emma go potty, too."
 
 What would you like to ask C to do?
=> hush
<= You say, "C, please hush"
 C’s response:
 "C hush."
 "Papa hush, too."
 "Mama hush, too."
 "Ruby hush, too."
 "Nono hush, too."
 "Emma hush, too."
 
 What would you like to ask C to do?
=> stop
<= You say, "C, please stop"
 C’s response:
 "C stop."
 "Papa stop, too."
 "Mama stop, too."
 "Ruby stop, too."
 "Nono stop, too."
 "Emma stop, too."
 

Yeah, that’s about what it was like. You couldn’t sneeze without hearing about Emma or Nono sneezing, too.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.219.32