# `if` and `if let` expressions
## `if` expressions
> **Syntax**\
> _IfExpression_ :\
> `if` [_Expression_]_except struct expression_ [_BlockExpression_]\
> (`else` (
> [_BlockExpression_]
> | _IfExpression_
> | _IfLetExpression_ ) )\?
An `if` expression is a conditional branch in program control.
The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block.
The condition operands must have the [boolean type].
If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped.
If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated.
If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed.
An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated.
An `if` expression must have the same type in all situations.
```rust
# let x = 3;
if x == 4 {
println!("x is four");
} else if x == 3 {
println!("x is three");
} else {
println!("x is something else");
}
let y = if 12 * 15 > 150 {
"Bigger"
} else {
"Smaller"
};
assert_eq!(y, "Bigger");
```
## `if let` expressions
> **Syntax**\
> _IfLetExpression_ :\
> `if` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_
> [_BlockExpression_]\
> (`else` (
> [_BlockExpression_]
> | _IfExpression_
> | _IfLetExpression_ ) )\?
An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand.
If the value of the scrutinee matches the pattern, the corresponding block will execute.
Otherwise, flow proceeds to the following `else` block if it exists.
Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated.
```rust
let dish = ("Ham", "Eggs");
// this body will be skipped because the pattern is refuted
if let ("Bacon", b) = dish {
println!("Bacon is served with {}", b);
} else {
// This block is evaluated instead.
println!("No bacon will be served");
}
// this body will execute
if let ("Ham", b) = dish {
println!("Ham is served with {}", b);
}
if let _ = 5 {
println!("Irrefutable patterns are always true");
}
```
`if` and `if let` expressions can be intermixed:
```rust
let x = Some(3);
let a = if let Some(1) = x {
1
} else if x == Some(2) {
2
} else if let Some(y) = x {
y
} else {
-1
};
assert_eq!(a, 3);
```
An `if let` expression is equivalent to a [`match` expression] as follows:
```rust,ignore
if let PATS = EXPR {
/* body */
} else {
/*else */
}
```
is equivalent to
```rust,ignore
match EXPR {
PATS => { /* body */ },
_ => { /* else */ }, // () if there is no else
}
```
Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions:
```rust
enum E {
X(u8),
Y(u8),
Z(u8),
}
let v = E::Y(12);
if let E::X(n) | E::Y(n) = v {
assert_eq!(n, 12);
}
```
The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]).
When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
```rust,ignore
// Before...
if let PAT = EXPR && EXPR { .. }
// After...
if let PAT = ( EXPR && EXPR ) { .. }
// Before...
if let PAT = EXPR || EXPR { .. }
// After...
if let PAT = ( EXPR || EXPR ) { .. }
```
[_BlockExpression_]: block-expr.md
[_Expression_]: ../expressions.md
[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
[_Pattern_]: ../patterns.md
[_Scrutinee_]: match-expr.md
[_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018
[`match` expression]: match-expr.md
[boolean type]: ../types/boolean.md
[scrutinee]: ../glossary.md#scrutinee