5.Control expressions
5.1.Truthy and falsey values
A truthy value is a value that is considered true for an if, unless, while or until guard. A falsey value is a value that is considered false in those places.
The only falsey values are nil, false and null pointers (pointers whose memory address is zero). Any other value is truthy.
5.2.if
An if evaluates the then branch if its condition is truthy, and evaluates the else branch, if there’s any, otherwise.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
To write a chain of if-else-if you use elsif:
1 2 3 4 5 6 7 |
|
After an if, a variable’s type depends on the type of the expressions used in both branches.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Note that if a variable is declared inside one of the branches but not in the other one, at the end of the if it will also contain the Nil type.
Inside an if’s branch the type of a variable is the one it got assigned in that branch, or the one that it had before the branch if it was not reassigned:
1 2 3 4 5 6 7 |
|
That is, a variable’s type is the type of the last expression(s) assigned to it.
If one of the branches never reaches past the end of an if, like in the case of a return, next, break or raise, that type is not considered at the end of the if:
1 2 3 4 5 6 7 8 |
|
5.3.unless
An unless evaluates the then branch if its condition is falsey, and evaluates the else branch, if there’s any, otherwise. That is, it behaves in the opposite way of an if:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
5.4.case
A case is a control expression that allows a sort of pattern matching. It allows writing a chain of if-else-if with a small change in semantic and some more powerful constructs.
In its basic form, it allows matching a value against other values:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Note that === is used for comparing an expression against a case’s value.
If a when’s expression is a type, is_a? is used. Additionally, if the case expression is a variable or a variable assignment the type of the variable is restricted:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
You can invoke a method on the case’s expression in a when by using the implicit-object syntax:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Finally, you can ommit the case’s value:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
This sometimes leads to code that is more natural to read.
5.5.while
A while executes its body as long as its condition is truthy
1 2 3 |
|
In the above form, the condition is first tested and, if truthy, the body is executed. That is, the body might never be executed.
To execute the body at least once and then continue executing it while the condition is truthy, write the while as a prefix:v
1
|
|
If you need to execute multiple expressions, group them between begin and end:
1 2 3 4 |
|
A while’s type is always Nil.
Similar to an if, if a while’s condition is a variable, the variable is guaranteed to not be nil inside the body. If the condition is an var.is_a?(Type) test, var is guaranteed to be of type Type inside the body. And if the condition is a var.responds_to?(:method), var is guaranteed to be of a type that responds to that method.
The type of a variable after a while depends on the type it had before the while and the type it had before leaving the while’s body:
1 2 3 4 5 6 7 8 |
|
5.6.until
An until executes its body until its condition is truthy. An until is just syntax sugar for a while with the condition negated:
1 2 3 4 5 6 7 8 |
|
An until can also be used in its suffix form, causing the body to be executed at least once. break and next can also be used inside an until.
5.7.&&
An && (and) evaluates its left hand side. If its truthy, it evaluates its right hand side and has that value. Otherwise it has the value of the left hand side. Its type is the union of the types of both sides.
You can think an && as syntax sugar of an if:
1 2 3 4 5 6 7 8 9 |
|
5.8.||
An || (or) evaluates its left hand side. If its falsey, it evaluates its right hand side and has that value. Otherwise it has the value of the left hand side. Its type is the union of the types of both sides.
You can think an || as syntax sugar of an if:
1 2 3 4 5 6 7 8 9 |
|
I will present about types and methods in part 3. Thanks!