홈강좌Rust 입문·중급 47편 중 27편째
Rust if let 과 let else — 한 경우만 볼 때 match 를 줄여 쓴다
Rust 의 if let Some(x) = 값 { } 은 그 경우일 때만 실행하는, 갈래 하나짜리 match 다. let Some(x) = 값 else { return …; }; 은 아니면 바로 빠져나가고, 맞으면 x 를 그 아래에서 계속 쓴다. let else 의 else 블록이 빠져나가지 않으면 E0308 이 난다.
01 if let — 한 경우만 볼 때
쿠폰이 있을 때만 할인 문구를 찍어 보자. 25편의 match 로 쓰면 None => {} 처럼 아무것도 안 하는 갈래를 하나 더 써야 한다. if let 은 그 갈래를 생략한다.
fn main() {
let coupon: Option<u32> = Some(3000);
if let Some(amount) = coupon {
println!("discount {amount} won");
}
let none: Option<u32> = None;
if let Some(amount) = none {
println!("discount {amount} won");
} else {
println!("no coupon");
}
} Compiling coupon v0.1.0 (~/projects/coupon)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
Running `target/debug/coupon`
discount 3000 won
no couponif let Some(amount) = coupon은 "coupon이Some이면, 안의 값을amount로 꺼내서 중괄호를 실행하라" 는 뜻이다.=가 하나지만 대입이 아니라 "이 모양에 맞는가" 를 묻는 것이다.- 맞지 않으면(
None) 건너뛴다.else를 붙이면 맞지 않을 때 실행할 곳을 정한다.
match 와 달리 다른 경우를 빠뜨려도 E0004 가 나지 않는다. 다른 경우는 "아무것도 안 한다" 고 정한 것이기 때문이다. 짧은 대신 빠짐없는지 검사해 주는 힘은 잃는다.
02 let else — 아니면 빠져나간다
함수 맨 앞에서 "값이 없으면 바로 끝낸다" 를 쓸 때는 let else 가 깔끔하다.
fn price_after(price: u32, coupon: Option<u32>) -> u32 {
let Some(amount) = coupon else {
return price;
};
price - amount
}
fn main() {
println!("{}", price_after(12000, Some(3000)));
println!("{}", price_after(12000, None));
} Compiling coupon v0.1.0 (~/projects/coupon)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/coupon`
9000
12000let Some(amount) = coupon else { return price; };은 맞으면amount를 만들고 다음 줄로 간다. 맞지 않으면else블록을 실행한다.if let과 달리 꺼낸amount를 그 아래 줄에서 계속 쓸 수 있다. 중괄호 안에 갇히지 않는다.- 끝의 세미콜론을 잊지 않는다.
let문이기 때문이다.
03 실습 — else 가 빠져나가지 않으면
else 블록에서 문구만 찍고 return 을 빼 보자.
fn price_after(price: u32, coupon: Option<u32>) -> u32 {
let Some(amount) = coupon else {
println!("no coupon");
};
price - amount
}
fn main() {
println!("{}", price_after(12000, None));
}error[E0308]: `else` clause of `let...else` does not diverge
--> src/main.rs:2:36
|
2 | let Some(amount) = coupon else {
| ____________________________________^
3 | | println!("no coupon");
4 | | };
| |_____^ expected `!`, found `()`
|
= note: expected type `!`
found unit type `()`
= help: try adding a diverging expression, such as `return` or `panic!(..)`- 무엇 —
let...else의else가 빠져나가지 않는다(does not diverge). - 어디 — 2~4번째 줄의
else블록 전체를 선으로 묶었다.!는 "여기서 끝나고 다음 줄로 안 간다" 는 뜻의 타입인데, 블록이()(11편의 값 없음)로 끝났다. - 고치는 법 —
help:가return이나panic!(..)처럼 빠져나가는 식을 넣으라고 한다. 아니면match를 쓰라고 한다.
else 를 그냥 지나가게 두면 그 아래에서 amount 를 쓸 때 값이 없다. 그래서 else 는 반드시 return 같은 것으로 함수를 빠져나가야 한다. 13편의 반복 안이라면 continue 나 break 도 된다.
| 쓰는 것 | 쓰는 때 |
|---|---|
match | 경우를 모두 다룬다 |
if let | 한 경우일 때만 무언가 한다 |
let else | 아니면 일찍 빠져나가고, 맞으면 꺼낸 값으로 계속한다 |
다음 편은 길이가 늘었다 줄었다 하는 목록, Vec 이다.