In this course, we'll study Booleans and conditions in Pharo.
There are two Booleans objects: true and false.
true is the only instance of the class True.
false is the only instance of the class False.
We'll send messages to these objects to set Boolean operations
or alternative structures such as ifTrue:IfFalse:, etc.
We'll study this.
In the first example of this slide,
you send the message &, a binary operator,
to the object false.
You pass it a parameter, which is all this.
It's an expression between parentheses, (1 error:'crazy').
This expression triggers an error.
You can see the evaluation of this whole expression triggers an error.
Why? Because the operand has also been evaluated
in this Boolean expression.
The operand has been evaluated, hence the mistake.
If you want to get the lazy version of the Boolean operators,
you must use the method and: of the class Boolean.
This method takes a block as a parameter.
Blocks start with [ and end with ].
They contain expressions, but the definition of a block
doesn't trigger the execution of its expressions.
For now, these expressions are not evaluated.
It is only if the first operand is true or false
that the block passed as a parameter is evaluated.
In the second example, you have false and: a block.
It returns false without evaluating the block passed as a parameter.
It is a typical lazy operator but built using blocks.
In Pharo, conditionals (if, false, while, etc.)
are always messages sent to Booleans or blocks.
Let's take another example:
the message ifTrue:ifFalse:, the typical alternative of any programming language.
But in Pharo, it's actually a message:
I can send the message ifTrue:ifFalse to a Boolean object.
This expression returns a Boolean.
I pass two blocks as parameters of this message:
one block is evaluated if the receiver Boolean is true,
the other if the receiver is false.
Careful: the message ifTrue:ifFalse:
is heavily used by Pharo: it's at the heart of the system.
It's so important that it's been heavily optimized
to be efficient without slowing down the entire system.
Let's talk again about Boolean implementation in Pharo:
it's extremely elegant.
the objects true and false are both instances of the classes True and False
which inherit the class Boolean.
Each of these classes define a set of methods
to return the expected behavior.
We'll give you more information about this elegant implementation
in a further lesson.
Back to the message ifTrue:ifFalse:.
There are different versions of these messages.
There's a version with only ifTrue: with a block as a parameter
to return only the first part of the alternative.
The message ifTrue:ifFalse takes two blocks
to return an alternative when the Boolean is true or false.
There are several examples here.
This only sends the message ifTrue:
with only one block to execute if the expression is true.
In this example, there's one block to execute:
this one if the receiver Boolean is true,
that one if it is false.
There are two different messages.
It's the same with ifFalse:
when it comes to the classes Boolean, True, and False.
There are other types of messages available to express conditions.
For instance, there's ifEmpty: ifNotempty:
which I can send to a collection.
With ifEmpty:, I pass a block.
The block is evaluated only if the receiver collection is or isn't empty.
ifNotEmpty: is the opposite condition.
If the collection isn't empty, then you execute the block.
But there's an extra problem:
this block takes an argument as a parameter
which is the non-empty collection.
The collection might be the result of a complex computation.
You can query once more for the collection.
If the collection isn't empty, it is passed as the block's parameter.
It can be used in the expressions of the block.
In this session,
we saw Booleans are normal objects in Pharo
and instances of the classes True and False which inherit Booleans.
You can send them messages.
These messages define all the constructions of alternatives
or of possible conditions in Pharo.
In other languages, it would rather be structures in the compiler.