Boolean and simplify expressions!
by Trebor777
Introduction
Hi, a little tutorial about those booleans... (object with a true or false value) and more specially about their operations.
What is a boolean?
A boolean, in logic, is something which have a 1 or 0 value,( true or false value).
In ruby, every defined object is true, except for the False class and the Nil class.
So by just testing an object you obtain a condition statement:
Object State
An object, is true, if it's defined, and has a value different from nil or false.
Knowing this can be useful to test if the object is supposed to have a value or not.
but be careful, undefined objects are different from objects with a nil value.
By undefined, I mean an object which has not been evaluatued/call/assigned by ruby, like if I call a variable that is not in my code for example. To summarize an object which doesn't exist.
You can test this "definition" state, can be usefull, with generated variables on the fly, like if the variable name is created by the program but not by the programmer.
In order to test if an object is defined:
If the object is not defined, it'll return nil, else it'll return a string about what object it is: 'local-variable', 'method', 'constant', etc...
A quick case of generated variables on the fly:
This piece of code, will create 10 variables having a value of 1,2,4,8,16...512, and called variable_0, variable_1.....variable_9
Object != Methods
Well now, you know that very existing object is true. But don't be confused with methods.
Methods can have return values(and if they don't they return the value of the last method's expression), which means methods can have a "infinite" range of return values, it can be an integer, a string, a true, or a false, etc...
So when testing the result of a method, be carefull of the thing you want...
But anyway, let's get straight to the point, booleans operators!!
Boolean Expressions!
To make it easier to read, and understand, I'll use a '+' sign for the OR operator, and a '.' sign for AND. '!' is for the NOT operator.
So, how does it work?
# Description
OR:
a + b, returns true if at least one of the operand is true: returns true, if a is true OR if b is true, or if a and b are true.
AND:
a . b, returns true only if both operands are true.
NOT:
!a, returns the opposite of the operand: "not true is false" and "not false is true"
So you can play quite a lot with those, and there is basically a complete algebra for them! (known as the Boole Algebra, look at wikipedia for more details)
There are some thing and tricks to know about them!
# Precedence
But first, I need to talk about the precedence of those operators!
In ruby, AND is equivalent to &&
and OR is similar to ||
the only difference is the precedence of those operators: AND, OR, have the same precedence. so you'll sometimes need parenthesis to write exactly what you want.
But && is stronger than || , meaning it'll go first!
In ruby:
a AND b OR c can be different than c OR a AND b
which can lead to some unexpected result, as it'll be the first operator being seen, that'll be evaluated, but with && and ||:
a && b || c is the always the same as c || a && b.
If you test this:
You'll see that a and b are different, even if it's the same expression!, a will be false, and b will be true. But why?
Let me explain, as I said OR and AND have the same "strenght" or precedence. So the first arrived wins:
so the first expression is evaluated like if it was like this:
a = (true or true) and false => true and false => false
But for b, && is stronger than ||:
b = true || (true && false) => true || (false) => true
It's like in classic algebra, the multiplication is stronger than the addition with && and || operators.
That's why we commonly use the . and the + in boole algebra.
Tricks and Tips
# A new friend
Imagine: you ONLY want that ONE value true between 2. Looks like a OR isn't it?
But OR is also true, if both values are true, arf .. damn how can I do this:
Let's try...
only one value, means: "one value and not the other OR the other and not the one"
=> a.!b + !a.b
ok... not too bad. It also means... "a or b , and not a and b"
=> (a+b). !(a.b)
But, how fantastic, there is a function to call that, the XOR (not X-OR the super hero)!
XOR stands for eXclusive OR! And you know what??? it exists in ruby as well!!
It's the ^ symbol.
a XOR b, in ruby is a^b, pretty cool and neat!!^^
Now.. let's get dirty
# Some algebra, for simplification
Do you remember that math rules called distributivity? You know:
2*(3+4) = 2*3 + 2*4
well that's the same in booleans:
a.(b + c) = a.b + a.c
but it's a bit different in the other way:
a + (b.c) = (a + b).(a + c)
We know this:
a + a + a = a
and that:
a.a.a = a
(1+1+1 = 1, 0+0+0 = 0, 1.1.1 = 1, and 0.0.0 = 0 )
So if you see this:
a + a.b
or that:
a.(a + b)
They are both equivalent to just: a
Let's see why:
a+ a.b, if a = 1, then a.b is b, so it becomes, a + b, as a =1, it's 1+b, so it's 1, so it's a.
if a = 0, it's 0 + 0.b, so it's 0 + 0, so it's 0 so it's a.
For the other one:
if a = 1, 1.(1+b) => 1.1 => 1 => a
if a = 0, 0.(0+b) => 0.b => 0 => a
This phenomenom is called absorbption.
Some simplification now!
a + !a . b = a + b
a . ( !a + b ) = a . b
1st case:
a = 1, b = 1:
1 + !1.1 => 1+ 0.1 => 1+0 => 1 ( a+b => 1 if a=1 and b = 1 )
a = 1, b = 0:
1 +!1.0 => 1+0.0 => 1+0 => 1 ( a+b => 1 if only a = 1)
a = 0,b = 0:
0+ !0.0 => 0 + 1.0 => 0+0 => 0 ( a+b => 0 if a=0 and b = 0)
a = 0, b = 1:
0+ !0.1 => 0 + 1.1 => 0+1 => 1 (a+b => 1 if only b = 1)
2nd case: a . ( !a + b ) = a . b
lets apply distributivity:
a.(!a+b) => a.!a + a.b => a.!a is always 0.=> 1.0=0, 0.1 = 0 => 0+a.b => a.b
Not so hard :D!
Now, a nice theorem!
!(a+b) = !a . !b
!(a.b) = !a + !b
can be usefull to know it in some case.
also works with any number of operand:
!(a+b+c) = !a . !b . !c
but what about:
!(a+b+ !c ) ? or !(a.b.!c)?
still works:p
!(a+b+ !c) => !a.!b.c ( !!c => c)
!(a.b.!c) => !a+!b+c
RGSS application
You're going to tell me: "What the point with RGSS??" Let me answer this question!
Some times, you can write in one line something written in 4. I can't stand it when I see useless code.
Example (extracted from the anti-lag script. : ):
I say: "Oh my god!"
I'll replace here, to make things easier, the conditions, by variables:
Original code:
Ok, first...let's write it in 2 lines:
Translated to english: "return false if (condition is true) else return true."
So as we said earlier, everything have a true value, or at least for condition statements, 2 (a true and false)
It means:
(a or b or c or d) return a true or false value. Oh my god, but isn't it what we are returning???
But as we want the opposite of the condition statement value we need a NOT:
Ok, much better, five lines to one, and still readable; but still, we can do a bit more! (especially in this scenario)
with the theorem talk about previously, our code can become this:
So if we look at it, we replace that by the variable's values:
Good for us, ! .. <= ... is .. > .. so let's remove those '!' .
Good good! A lot better isn't it? But... I remember, there is a method for testing a number between 2 others! It's called between?(min, max)
Yahooo!! So simple and readable!
That's why sometime it's good to know about booleans!
It's the same with:
can be:
Of course, doesn't apply if you got stuff between the 2 if statement like
You can also simplify your code, with if and unless...just be carefull to switch the value, as unless is a: if NOT, so
It's:
but I want to use a if: No problem!
becomes:
As we said before, everything which has a value, is true, else it's false. So it's useless to test a value about it's trueness... if you want to test its non value, then ask the opposite of the trueness...So don't write:
but
Remember, clean and neat code , is always better!
Tip of the day:
don't write:
- c == nil but c.nil? (by extension: c != nil => !c.nil?)
- c == "", c == [], c == {} but c.empty? (by extension c != "" => !c.empty?)
by Trebor777
Introduction
Hi, a little tutorial about those booleans... (object with a true or false value) and more specially about their operations.
What is a boolean?
A boolean, in logic, is something which have a 1 or 0 value,( true or false value).
In ruby, every defined object is true, except for the False class and the Nil class.
So by just testing an object you obtain a condition statement:
Code:
if object
do_something
end
Object State
An object, is true, if it's defined, and has a value different from nil or false.
Knowing this can be useful to test if the object is supposed to have a value or not.
but be careful, undefined objects are different from objects with a nil value.
By undefined, I mean an object which has not been evaluatued/call/assigned by ruby, like if I call a variable that is not in my code for example. To summarize an object which doesn't exist.
You can test this "definition" state, can be usefull, with generated variables on the fly, like if the variable name is created by the program but not by the programmer.
In order to test if an object is defined:
Code:
defined? object
A quick case of generated variables on the fly:
Code:
10.times{|i| eval("variable_#{i} = 2**i }")
Object != Methods
Well now, you know that very existing object is true. But don't be confused with methods.
Methods can have return values(and if they don't they return the value of the last method's expression), which means methods can have a "infinite" range of return values, it can be an integer, a string, a true, or a false, etc...
So when testing the result of a method, be carefull of the thing you want...
But anyway, let's get straight to the point, booleans operators!!
Boolean Expressions!
To make it easier to read, and understand, I'll use a '+' sign for the OR operator, and a '.' sign for AND. '!' is for the NOT operator.
So, how does it work?
# Description
OR:
a + b, returns true if at least one of the operand is true: returns true, if a is true OR if b is true, or if a and b are true.
AND:
a . b, returns true only if both operands are true.
NOT:
!a, returns the opposite of the operand: "not true is false" and "not false is true"
So you can play quite a lot with those, and there is basically a complete algebra for them! (known as the Boole Algebra, look at wikipedia for more details)
There are some thing and tricks to know about them!
# Precedence
But first, I need to talk about the precedence of those operators!
In ruby, AND is equivalent to &&
and OR is similar to ||
the only difference is the precedence of those operators: AND, OR, have the same precedence. so you'll sometimes need parenthesis to write exactly what you want.
But && is stronger than || , meaning it'll go first!
In ruby:
a AND b OR c can be different than c OR a AND b
which can lead to some unexpected result, as it'll be the first operator being seen, that'll be evaluated, but with && and ||:
a && b || c is the always the same as c || a && b.
If you test this:
Code:
a = true or true and false
b = true || true && false
p a,b
Let me explain, as I said OR and AND have the same "strenght" or precedence. So the first arrived wins:
so the first expression is evaluated like if it was like this:
a = (true or true) and false => true and false => false
But for b, && is stronger than ||:
b = true || (true && false) => true || (false) => true
It's like in classic algebra, the multiplication is stronger than the addition with && and || operators.
That's why we commonly use the . and the + in boole algebra.
Tricks and Tips
# A new friend
Imagine: you ONLY want that ONE value true between 2. Looks like a OR isn't it?
But OR is also true, if both values are true, arf .. damn how can I do this:
Let's try...
only one value, means: "one value and not the other OR the other and not the one"
=> a.!b + !a.b
ok... not too bad. It also means... "a or b , and not a and b"
=> (a+b). !(a.b)
But, how fantastic, there is a function to call that, the XOR (not X-OR the super hero)!
XOR stands for eXclusive OR! And you know what??? it exists in ruby as well!!
It's the ^ symbol.
a XOR b, in ruby is a^b, pretty cool and neat!!^^
Now.. let's get dirty
# Some algebra, for simplification
Do you remember that math rules called distributivity? You know:
2*(3+4) = 2*3 + 2*4
well that's the same in booleans:
a.(b + c) = a.b + a.c
but it's a bit different in the other way:
a + (b.c) = (a + b).(a + c)
We know this:
a + a + a = a
and that:
a.a.a = a
(1+1+1 = 1, 0+0+0 = 0, 1.1.1 = 1, and 0.0.0 = 0 )
So if you see this:
a + a.b
or that:
a.(a + b)
They are both equivalent to just: a
Let's see why:
a+ a.b, if a = 1, then a.b is b, so it becomes, a + b, as a =1, it's 1+b, so it's 1, so it's a.
if a = 0, it's 0 + 0.b, so it's 0 + 0, so it's 0 so it's a.
For the other one:
if a = 1, 1.(1+b) => 1.1 => 1 => a
if a = 0, 0.(0+b) => 0.b => 0 => a
This phenomenom is called absorbption.
Some simplification now!
a + !a . b = a + b
a . ( !a + b ) = a . b
1st case:
a = 1, b = 1:
1 + !1.1 => 1+ 0.1 => 1+0 => 1 ( a+b => 1 if a=1 and b = 1 )
a = 1, b = 0:
1 +!1.0 => 1+0.0 => 1+0 => 1 ( a+b => 1 if only a = 1)
a = 0,b = 0:
0+ !0.0 => 0 + 1.0 => 0+0 => 0 ( a+b => 0 if a=0 and b = 0)
a = 0, b = 1:
0+ !0.1 => 0 + 1.1 => 0+1 => 1 (a+b => 1 if only b = 1)
2nd case: a . ( !a + b ) = a . b
lets apply distributivity:
a.(!a+b) => a.!a + a.b => a.!a is always 0.=> 1.0=0, 0.1 = 0 => 0+a.b => a.b
Not so hard :D!
Now, a nice theorem!
!(a+b) = !a . !b
!(a.b) = !a + !b
can be usefull to know it in some case.
also works with any number of operand:
!(a+b+c) = !a . !b . !c
but what about:
!(a+b+ !c ) ? or !(a.b.!c)?
still works:p
!(a+b+ !c) => !a.!b.c ( !!c => c)
!(a.b.!c) => !a+!b+c
RGSS application
You're going to tell me: "What the point with RGSS??" Let me answer this question!
Some times, you can write in one line something written in 4. I can't stand it when I see useless code.
Example (extracted from the anti-lag script. : ):
Code:
return false if @real_x <= screne_x
return false if @real_x >= screne_width
return false if @real_y <= screne_y
return false if @real_y >= screne_height
return true
I say: "Oh my god!"
I'll replace here, to make things easier, the conditions, by variables:
Original code:
Code:
return false if a
return false if b
return false if c
return false if d
return true
Ok, first...let's write it in 2 lines:
Code:
return false if a || b || c || d
return true
Translated to english: "return false if (condition is true) else return true."
So as we said earlier, everything have a true value, or at least for condition statements, 2 (a true and false)
It means:
(a or b or c or d) return a true or false value. Oh my god, but isn't it what we are returning???
But as we want the opposite of the condition statement value we need a NOT:
Code:
return !(a || b || c || d)
Ok, much better, five lines to one, and still readable; but still, we can do a bit more! (especially in this scenario)
with the theorem talk about previously, our code can become this:
Code:
return !a && !b && !c && !d
So if we look at it, we replace that by the variable's values:
Code:
return !@real_x <= screne_x && !@real_x >= screne_width && !@real_y <= screne_y && !@real_y >= screne_height
Good for us, ! .. <= ... is .. > .. so let's remove those '!' .
Code:
return @real_x > screne_x && @real_x < screne_width && @real_y >screne_y && @real_y < screne_height
Good good! A lot better isn't it? But... I remember, there is a method for testing a number between 2 others! It's called between?(min, max)
Code:
return (@real_x.between?(screne_x, screne_width) && @real_y.between?(screne_y,screne_height))
Yahooo!! So simple and readable!
That's why sometime it's good to know about booleans!
It's the same with:
Code:
if Condition
if condition2
do_something
end
end
can be:
Code:
if condition and condition2
do_something
end
Of course, doesn't apply if you got stuff between the 2 if statement like
Code:
if c1
do somthing
if c2
do_somehtingelse
end
end
#OR
if c1
if c2
do_somethingelse
end
do_something
end
You can also simplify your code, with if and unless...just be carefull to switch the value, as unless is a: if NOT, so
Code:
unless c1
if c2
do something
end
end
It's:
Code:
unless c1 and !c2
do_something
end
but I want to use a if: No problem!
Code:
if not (c1 and !c2)
do something
end
becomes:
Code:
if !c1 or c2
do something
end
As we said before, everything which has a value, is true, else it's false. So it's useless to test a value about it's trueness... if you want to test its non value, then ask the opposite of the trueness...So don't write:
Code:
if c == true
#or
if c==false
but
Code:
if c
#or
if !c
Remember, clean and neat code , is always better!
Tip of the day:
don't write:
- c == nil but c.nil? (by extension: c != nil => !c.nil?)
- c == "", c == [], c == {} but c.empty? (by extension c != "" => !c.empty?)