docs: revise branching, classes, index, looping, qa, syntax docs and add concurrency/error-handling nav entries

This commit is contained in:
Bob Nystrom
2014-01-21 05:44:51 +00:00
parent a5c4918a75
commit 781ccf3fb6
9 changed files with 116 additions and 125 deletions
+11 -11
View File
@@ -1,27 +1,27 @@
^title Branching
*Flow control* is used to determine which chunks of code are executed and how many times. Expressions and statements for deciding whether or not to execute some code are called *branching* and are covered here. To execute something more than once, you'll want [*looping*](looping.html).
*Control flow* is used to determine which chunks of code are executed and how many times. Expressions and statements for deciding whether or not to execute some code are called *branching* and are covered here. To execute something more than once, you'll want [*looping*](looping.html).
## Truthiness
Flow control is about evaluating an expression and then choosing which code to execute based on whether or not the result is "true". That's easy if the value happens to be a boolean, but what if it's some other type?
Branching is conditional on the value of some expression. We take the entire universe of possible values and divide them into two buckets: some we consider "true" and the rest are "false". If the expression results in a value in the true bucket, we branch one way. Otherwise, we go the other way.
Languages handle this by having a set of rules for what values of any given type are "true" and will cause a condition to be met. Wren calls this "truthiness" and "falsiness". The rules are simple (and follow Ruby):
Obviously, the boolean `true` is in the "true" bucket and `false` is in "false", but what about values of other types? The choice is ultimately arbitrary, and different languages have different rules. Wren's rules follow Ruby:
* The boolean value `false` is falsey.
* The null value `null` is falsey.
* Everything else is truthy.
* The boolean value `false` is false.
* The null value `null` is false.
* Everything else is true.
This means `0`, empty strings, and empty collections are all considered truthy values.
This means `0`, empty strings, and empty collections are all considered "true" values.
## If statements
The simplest flow control structure, `if` lets you conditionally skip a chunk of code. It looks like this:
The simplest branching statement, `if` lets you conditionally skip a chunk of code. It looks like this:
:::wren
if (ready) io.write("go!")
That will evaluate the parenthesized expression after `if`. If it's truthy, then the expression after the condition is evaluated. Otherwise it is skipped. Instead of an expression, you can have a block:
That evaluates the parenthesized expression after `if`. If it's true, then the statement after the condition is evaluated. Otherwise it is skipped. Instead of a statement, you can have a block:
:::wren
if (ready) {
@@ -29,7 +29,7 @@ That will evaluate the parenthesized expression after `if`. If it's truthy, then
io.write("go!")
}
You may also provide an `else` branch. It will be evaluated if the condition is falsey:
You may also provide an `else` branch. It will be executed if the condition is false:
:::wren
if (ready) io.write("go!") else io.write("not ready!")
@@ -44,7 +44,7 @@ And, of course, it can take a block too:
## The logical operators `&&` and `||`
The `&&` and `||` operators are lumped here under flow control because they conditionally execute some code—they short-circuit. Both of them are infix operators, and, depending on the value of the left-hand side, the right-hand operand expression may or may not be evaluated.
The `&&` and `||` operators are lumped here under branching because they conditionally execute some code—they short-circuit. Both of them are infix operators, and, depending on the value of the left-hand side, the right-hand operand expression may or may not be evaluated.
An `&&` ("logical and") expression evaluates the left-hand argument. If it's falsey, it returns that value. Otherwise it evaluates and returns the right-hand argument.