The fifth part of the translation is
D Programming Language Tutorial by
Ali Çehreli . In this part the chapter Logical Expressions is translated. Chapter material is designed for beginners.
- Part 1
- Part 2
- Part 3
- Part 4
Boolean expressions
The actual work that the program performs is in expressions. Any part of a program that creates a value or a side effect is called an expression. It is defined by a broad concept, because even a constant value, say 42, and a string value, for example “hello”, are expressions, since they create these corresponding constants 42 and “hello”.
Important: Do not confuse creating a value with a variable declaration. Values do not need to bind to variables.')
Function calls, such as
writeln , are expressions, by the way, because they have side effects. In the case of
writeln , this effect is superimposed on the standard output stream by printing characters on it. Another example of the programs that we wrote earlier may be an assignment operation, which changes the variable that is on the left.
Because of the creation of values, expressions may participate in other expressions. This allows us to form more complex expressions from simpler ones. For example, suppose that there is a function called
currentTemperature , which returns the value of the current air temperature, this value that it produces can be directly used in the
writeln expression:
writeln("It's ", currentTemperature()," degrees at the moment.")
This line contains the following:
- “It's”
- currentTemperature ()
- "degrees at the moment.
- writeln () is an expression that uses the previous three.
In this chapter, we will discuss the specific types of expressions that are used in conditional statements.
Before going further I would like to repeat the assignment statement again, now emphasizing these two expressions that are on the left and right of it. The assignment operator (=) assigns the value of the specified expression to the right of the expression to the left (for example, a variable).
temperature = 23
Boolean expressions
Logical expressions are expressions that are used in Boolean algebra. Logical expressions are what computer programs do, making decisions like "if the answer is yes, I will save the file."
Boolean expressions can have one of two values:
false , meaning false, and
true , meaning true.
I will use
writeln expressions in the following examples. If the line prints
true at the end, it will mean that what is printed on this line is true. Similarly,
false will mean that what is printed is false. For example, if this program output is:
There is coffee: true
it will mean "there is coffee." Similarly:
There is coffee: false
would mean "there is no coffee." Please note that in reality the “is” located on the left does not mean that there is coffee. I use the construct "... is ...: false" to mean "this is not so" or "this is false." Logical expressions are actively used in predicates, cycles, function arguments, etc. It is important to understand how they work. Fortunately, logical expressions are very simple to explain and easy to use.
Below are the logical operators that are used in logical expressions:
- The equality operator (==) answers the question “is this equal to this?”. It compares the two expressions to its left and returns true if they are equal and false if not. Essentially, the value returned by the equality operator (==) is a logical expression.
As an example, suppose we have these two variables: int daysInWeek = 7; int monthsInYear = 12;
Next, these are two logical expressions that use these values: daysInWeek == 7 // true monthsInYear == 11 // false
- The inequality operator (! =) Answers the question “this is not equal to this”. It compares these two expressions on both sides and returns the opposite of what the operator (==) returns
daysInWeek != 7 // false monthsInYear != 11 // true
- The disjunction operator (||) denotes "or", and returns true if any of the logical expressions is true
If the value of the expression on the left is true , then the operator will return true and will not even look at the expression on the right. If the expression on the left returns false , the operator returns the value of the expression on the right. This operator is similar to the union "or" in Russian.
Left expression | Operator | Right expression | Result |
---|
false | || | false | false |
false | || | true | true |
true | || | false (doesn't matter) | true |
true | || | true (doesn't matter) | true |
import std.stdio; void main() { // false "", true "" bool existsCoffee = false; bool existsTea = true; writeln("There is warm drink: ", existsCoffee || existsTea); }
Because at least one of the two expressions, the true logical expression above returns true. - The conjunction operator (&&) denotes "and" and returns true if both expressions, left and right, return true .
If the value of the expression on the left is false , the operator will return false and will not even look at the expression on the right. If the expression on the left returns true , then the operator returns the value of the expression on the right. This operator is similar to the union “and” in Russian.Left expression | Operator | Right expression | Result |
---|
false | && | false (doesn't matter) | false |
false | && | true (doesn't matter) | false |
true | && | false | false |
true | && | true | true |
- The strict disjunction operator (^) answers the question “one or the other, but not both?”. This statement returns true if only one expression returns true , but not both.
Left expression | Operator | Right expression | Result |
---|
false | ^ | false | false |
false | ^ | true | true |
true | ^ | false | true |
true | ^ | true | false |
For example, this logic that represents: "I will play chess, if only one of two friends comes." This can be programmed as follows: writeln("I will play chess: ", jimShowedUp ^ bobShowedUp)
- The operator is strictly less (<) answers the question “Is it less than this?” (Or “Will it be higher when sorting?”)
writeln("We beat: ", theirScore < ourScore)
- The operator strictly more (>) answers the question “Is it more than that?” (Or “Will it be lower when sorting?”.)
writeln("They beat: ", theirScore > ourScore)
- The operator is less stringent (<=) answers the question “Is it less or equal to this?” (Or “Will it be higher on sorting or on the same query?”.)
writeln("We were not beaten: ", theirScore <= ourScore)
- The operator is less strictly less (> =) answers the question “Is it greater or equal to this?” (Or “Will it be lower or with the same query when sorting?”.)
writeln("We did not beat: ", theirScore >= ourScore)
- The inversion operator (!) Means "This is the opposition of something." It differs from previous statements in that it works with only one expression and returns true if the expression returns false , and returns false if the expression returns true .
writeln("I will walk: ", !existsBicycle)
Expression grouping
The order in which these expressions are evaluated can be specified using parentheses. They can also be grouped. When expressions in brackets fall into more complex expressions, the values of these expressions are calculated before they are used in the expressions in which they fall. For example, this expression “if there is coffee or tea, as well as a cookie or a bun, then I am happy” can be programmed in approximately the following way:
writeln("I am happy: ", (existsCoffee || existsTea) && (existsCookie || existsScone))
If these nested expressions were not enclosed in parentheses, then they will be executed taking into account the operators' priorities according to rules D (which were inherited from the C language). Since the conjunction operator
&& priority is higher than that of the disjunction operator
|| , writing an expression without parentheses will not be calculated as expected.
writeln("I am happy: ", existsCoffee || existsTea && existsCookie || existsScone)
The conjunction operator
&& will execute first, and the entire expression will be semantically equivalent to the following expression:
writeln("I am happy: ", existsCoffee || (existsTea && existsCookie) || existsScone)
This has a different meaning: “If there is coffee or tea with cookies or a bun, then I'm happy.”
Reading bool type input
All
bool values above are printed as “false” or “true”. But this does not work in the opposite direction: these lines are “false” and “true” are not automatically read as values
false and
true . For this reason, this input must be read as strings and then converted to values of type
bool .
Since in one of the exercises below you need to enter “false” and “true”, I have to use the features of D, which I have not explained to you yet. I have described below a method that converts the specified string input data to
bool data. This method will solve this problem by running
to , which is declared in the
std.conv module. (You may see a
ConvException error if you type anything other than "false" or "true.")
I hope that all parts of the code that are in
main () in the following programs are understandable at this stage.
read_bool () is the method in which there are new, for you, language features. Although I put in comments for what he does, you can ignore this method. Still, it must be in the program code for compilation and correct operation.
Exercises
- We saw above that these < and > operators were used to determine when the value is greater and when less than another value, but there was no operator that answers the question “is it between?” To determine when the value is between two other values.
Let's assume that the programmer wrote the following code to determine when value is between 10 and 20. Notice that the program does not compile as described. import std.stdio; void main() { int value = 15; writeln("Is between: ", 10 < value < 20);
Try to bracket this whole expression: writeln("Is between: ", (10 < value < 20));
Note that this program will not compile anyway. - While searching for a solution to this problem, the same programmer discovers that the following use of brackets allows you to compile the code:
writeln("Is between: ", (10 < value) < 20);
Note that the program now works as intended and displays "true". Unfortunately, this output is confusing, because there is a bug in this program. You can see the consequences of this bug by replacing 15 with a value greater than 20: int value = 21;
Notice that the program still displays "true", despite the fact that 21 is not less than 20. Hint: Remember that the type of the logical expression is bool . It should not make sense when the bool is less than 20. - Logical expressions that answer the question “Is it between?” Should, instead, answer the question: “Is it more than the minimum value and less than the maximum?”.
Modify the expression in this program with this logic in mind and notice that it now displays "true", as expected. You can also test that this logical expression works correctly with other values. For example, when value is 50 or 1, this program should output “false” and when value is 12, this program will display “true”. - Suppose we can go to the beach when one of the following conditions is true:
- If the distance to the beach is less than 10 km and there are bicycles for everyone.
- If we are less than 6, and we have a car, and one of us has a driver's license.
As written, the following program always displays "true." Construct the logic so that the program will display "true" when one of the conditions above is satisfied. (When the program asks, enter "true" or "false" for questions that begin with the words "Is there a."). Remember to connect the read_bool () method when testing the program: import std.stdio; import std.conv; import std.string; void main() { write("How many are we? "); int personCount; readf(" %s", &personCount); write("How many bicycles are there? "); int bicycleCount; readf(" %s", &bicycleCount); write("What is the distance to the beach? "); int distance; readf(" %s", &distance); bool existsCar = read_bool("Is there a car? "); bool existsLicense = read_bool("Is there a driver license? "); writeln("We are going to the beach: ", true); } bool read_bool(string message) { // write(message, "(false or true) "); // . string input; while (input.length == 0) { input = chomp(readln()); } // bool result = to!bool(input); // return result; }
Enter different values and test this logical expression that you wrote, it works correctly.
… decision- Since the compiler takes 10 <value already as an expression, it expects a comma after it to accept it as an argument to writeln . Using parentheses around the whole expression will not work, because at this time the closing bracket will be expected in the same expression.
- Grouping this expression as (10 <value) <20 will remove the compile error, because in this case the first part will be calculated and then its result will be compared with <20
We know that the value of a logical expression, such as 10 <value , will be false or true . false and true take the values 0 and 1, respectively, in integer expressions. We will look at automatic type conversion in the following chapters. As a result, the whole expression will be equivalent to either 0 <20 or 1 <20 , which both return true . - The expression "greater than the minimum value and less than the maximum" can be programmed as follows:
writeln("Is between: ", (value > 10) && (value < 20))
- “Are there bikes for everyone” can be programmed as a personCount <= bicycleCount or so bicycleCount> = personCount . The rest of this logical expression can be immediately transferred to the program code from the exercise:
writeln("We are going to the beach: ", ((distance < 10) && (bicycleCount >= personCount)) || ((personCount <= 5) && existsCar && existsLicense) )
Note the location of this disjunction operator (||) makes reading easier by separating these two basic predicates.