This is actually something that stumps many people who come to using Ruby. Whilst you can use 'and' in the way you are, it doesn't actually work in the way you might be thinking it does. In fact, you might notice that these two keywords are explained under 'Control Flow' and not 'Evaluating expressions'. That's a big clue as to what the problem is and the person who wrote that guide has missed it (as many do).
Try this instead and make a note of what happens:
p 9 > 3 && 6 == 3 #true
Using 'and' and '&&' give two different results.
Also:
p (9 > 3 and 6 == 3) #false
The difference here is the added parenthesis and it seems to be working again. This might look like it's working as you think, but that's still not really the case.
Now try this:
p 1 > 10 or 5 == 5 #false
Here we are using 'or' instead. Our expected result, however, would be true because 5 == 5. This demonstrates a limiting factor of using the 'and' and 'or' keywords instead of using the operators && and || when it comes to evaluating the truthness of some statements.
Let's look at what is happening.
For example you could have the code:
def load_save_file if save_file_found #load save file data return true else return false end end load_save_file or raise "unable to load save file"
If upon calling and executing load_save_file, a save file is found and loaded, and true is returned, you will not get a raised exception. However, if the method is called and it does not load a save file, it will return false. In this case, the 'or' part will be run and we will get a raised exception which tells us it was not successful (you wouldn't use it like that, but for the example we will).
With your examples, it is working fine. However, the p is attached to the first part of the statement, and not the second. You'd be as well writing the code like this:
p 9 > 3 #prints true 6 == 3 #prints nothing because there's no p
What is happening is that it reads it more like this:
(p 9 > 3) and (6 == 3)
First it prints the outcome of 9 > 3, which is true. And then it simply operates 6 == 3, which is does register as false, but because there isn't a 'p' it doesn't print anything.
So, the thing to remember is that you shouldn't treat 'and' and 'or' as evaluating many things at once. It's more like saying: 'do this' and then 'do this if the first succeeds'. If the first part fails, the bit after 'and' doesn't get processed.
At least that's my interpretation, but I think I have the understanding correct.
Here's something little I just wrote up and the results of them. If you can follow the understanding, then that's good.
def some_method(value) if value > 5 p "true, #{value} is greater than 5" return true else p "false, #{value} is not greater than 5" return false end end some_method(10) and some_method(4) #prints "true, #{value} is greater than 5" and then "false, #{value} is not greater than 5" some_method(3) and some_method(6) #prints "false, #{value} is not greater than 5" ONLY some_method(8) or some_method(10) #prints "true, #{value} is greater than 5" ONLY some_method(3) or some_method(12) #prints "false, #{value} is not greater than 5" and then "true, #{value} is greater than 5"
It's not that the tutorial is wrong, they've just missed something of pretty great importance due to the way they've gone about writing it (and not read up on what is actually going on under the code).
Take a read of this article here:
http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ Spoiler for Additionally :
As an additional note to the guide you are using. When they talk about using 'boolean' values, you'll come to learn that this too isn't quite correct.
From an earlier post I wrote here:
http://rmrk.net/index.php/topic,46655.msg540272.html#msg540272 Ruby doesn't have a Boolean object type. It has two types in place of that: TrueClass and FalseClass. When you use the keyword 'true' or 'false' it is a keyword that references an object of the respective type (true is a TrueClass, false is a FalseClass). When you come to checking the object type with the .is_a? method, you will have to check for it being a TrueClass object or a FalseClass one. When you do something like this:
false_eval = (5 > 10) # false_eval = false p false_eval.class # FalseClass true_eval = (5 == 5) # true_eval = true p true_eval.class # TrueClass
This very quickly shows that, even though you aren't creating any objects of the type FalseClass and TrueClass, (5 > 10) returns a FalseClass object, which is then assigned to false_eval. The same happens even if you do:
false_eval = false p false_eval.class
All 'false' is, is a reference to an object of FalseClass. Same for 'true'.