1
- % ` if `
1
+ % if
2
2
3
- Rust' s take on ` if ` is not particularly complex, but it' s much more like the
4
- ` if ` you' ll find in a dynamically typed language than in a more traditional
5
- systems language. So let' s talk about it, to make sure you grasp the nuances.
3
+ Rust’ s take on ` if ` is not particularly complex, but it’ s much more like the
4
+ ` if ` you’ ll find in a dynamically typed language than in a more traditional
5
+ systems language. So let’ s talk about it, to make sure you grasp the nuances.
6
6
7
- ` if ` is a specific form of a more general concept, the * branch* . The name comes
7
+ ` if ` is a specific form of a more general concept, the ‘ branch’ . The name comes
8
8
from a branch in a tree: a decision point, where depending on a choice,
9
9
multiple paths can be taken.
10
10
@@ -20,11 +20,11 @@ if x == 5 {
20
20
21
21
If we changed the value of ` x ` to something else, this line would not print.
22
22
More specifically, if the expression after the ` if ` evaluates to ` true ` , then
23
- the block is executed. If it' s ` false ` , then it is not.
23
+ the block is executed. If it’ s ` false ` , then it is not.
24
24
25
25
If you want something to happen in the ` false ` case, use an ` else ` :
26
26
27
- ``` { rust}
27
+ ``` rust
28
28
let x = 5 ;
29
29
30
30
if x == 5 {
@@ -50,8 +50,7 @@ if x == 5 {
50
50
51
51
This is all pretty standard. However, you can also do this:
52
52
53
-
54
- ``` {rust}
53
+ ``` rust
55
54
let x = 5 ;
56
55
57
56
let y = if x == 5 {
@@ -63,95 +62,12 @@ let y = if x == 5 {
63
62
64
63
Which we can (and probably should) write like this:
65
64
66
- ``` { rust}
65
+ ``` rust
67
66
let x = 5 ;
68
67
69
68
let y = if x == 5 { 10 } else { 15 }; // y: i32
70
69
```
71
70
72
- This reveals two interesting things about Rust: it is an expression-based
73
- language, and semicolons are different from semicolons in other 'curly brace
74
- and semicolon'-based languages. These two things are related.
75
-
76
- ## Expressions vs. Statements
77
-
78
- Rust is primarily an expression based language. There are only two kinds of
79
- statements, and everything else is an expression.
80
-
81
- So what's the difference? Expressions return a value, and statements do not.
82
- In many languages, ` if ` is a statement, and therefore, ` let x = if ... ` would
83
- make no sense. But in Rust, ` if ` is an expression, which means that it returns
84
- a value. We can then use this value to initialize the binding.
85
-
86
- Speaking of which, bindings are a kind of the first of Rust's two statements.
87
- The proper name is a * declaration statement* . So far, ` let ` is the only kind
88
- of declaration statement we've seen. Let's talk about that some more.
89
-
90
- In some languages, variable bindings can be written as expressions, not just
91
- statements. Like Ruby:
92
-
93
- ``` {ruby}
94
- x = y = 5
95
- ```
96
-
97
- In Rust, however, using ` let ` to introduce a binding is _ not_ an expression. The
98
- following will produce a compile-time error:
99
-
100
- ``` {ignore}
101
- let x = (let y = 5); // expected identifier, found keyword `let`
102
- ```
103
-
104
- The compiler is telling us here that it was expecting to see the beginning of
105
- an expression, and a ` let ` can only begin a statement, not an expression.
106
-
107
- Note that assigning to an already-bound variable (e.g. ` y = 5 ` ) is still an
108
- expression, although its value is not particularly useful. Unlike C, where an
109
- assignment evaluates to the assigned value (e.g. ` 5 ` in the previous example),
110
- in Rust the value of an assignment is the unit type ` () ` (which we'll cover later).
111
-
112
- The second kind of statement in Rust is the * expression statement* . Its
113
- purpose is to turn any expression into a statement. In practical terms, Rust's
114
- grammar expects statements to follow other statements. This means that you use
115
- semicolons to separate expressions from each other. This means that Rust
116
- looks a lot like most other languages that require you to use semicolons
117
- at the end of every line, and you will see semicolons at the end of almost
118
- every line of Rust code you see.
119
-
120
- What is this exception that makes us say "almost"? You saw it already, in this
121
- code:
122
-
123
- ``` {rust}
124
- let x = 5;
125
-
126
- let y: i32 = if x == 5 { 10 } else { 15 };
127
- ```
128
-
129
- Note that I've added the type annotation to ` y ` , to specify explicitly that I
130
- want ` y ` to be an integer.
131
-
132
- This is not the same as this, which won't compile:
133
-
134
- ``` {ignore}
135
- let x = 5;
136
-
137
- let y: i32 = if x == 5 { 10; } else { 15; };
138
- ```
139
-
140
- Note the semicolons after the 10 and 15. Rust will give us the following error:
141
-
142
- ``` text
143
- error: mismatched types: expected `i32`, found `()` (expected i32, found ())
144
- ```
145
-
146
- We expected an integer, but we got ` () ` . ` () ` is pronounced * unit* , and is a
147
- special type in Rust's type system. In Rust, ` () ` is _ not_ a valid value for a
148
- variable of type ` i32 ` . It's only a valid value for variables of the type ` () ` ,
149
- which aren't very useful. Remember how we said statements don't return a value?
150
- Well, that's the purpose of unit in this case. The semicolon turns any
151
- expression into a statement by throwing away its value and returning unit
152
- instead.
153
-
154
- There's one more time in which you won't see a semicolon at the end of a line
155
- of Rust code. For that, we'll need our next concept: functions.
156
-
157
- TODO: ` if let `
71
+ This works because ` if ` is an expression. The value of the expression is the
72
+ value of the last expression in whichever branch was chosen. An ` if ` without an
73
+ ` else ` always results in ` () ` as the value.
0 commit comments