일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 26 | 27 | 28 | 29 | 30 | 31 |
- 링커
- vector
- Rust
- column space
- matrix
- 다익스트라
- 동적링크
- 스레드전용리소스
- CS정리
- 알고리즘
- 재배치
- 심벌 해석
- 행렬
- 코드포스
- 선형대수학
- eigenvalue
- 정적링크
- 적재도구loader
- rust 스터디
- 컴퓨터밑바닥의비밀
- 대상파일
- 구문트리
- c++
- 다이나믹 프로그래밍
- 백준
- linear algebra
- unity
- 컴파일러
- 스레드전용저장소
- 벡터
- Today
- Total
개발_기록용
RUST 스터디[RUST vs C++] 12. Pattern Matching 본문
https://google.github.io/comprehensive-rust/pattern-matching.html
Pattern Matching - Comprehensive Rust 🦀
This segment should take about 1 hour. It contains: SlideDuration Matching Values10 minutes Destructuring Structs4 minutes Destructuring Enums4 minutes Let Control Flow10 minutes Exercise: Expression Evaluation30 minutes
google.github.io
12.1 Matching Values
각각을 살펴보면
#[rustfmt::skip]
fn main() {
let input = 'x';
match input {
'q' => println!("Quitting"),
'a' | 's' | 'w' | 'd' => println!("Moving around"), : or를 사용해 case 처리 가능.
'0'..='9' => println!("Number input"), : 0~9와 같이 범위 가능.
key if key.is_lowercase() => println!("Lowercase: {key}"), : 조건을 만족하면, key를 받아서 오른쪽에 써먹을 수 있음.
_ => println!("Something else"), : 나머지가 Rust에선 _ *언더스코어 로 처리.
}
}
✔ 안 다루는 부분이 있다면 오류가 남.
예를 들어 우리가 i32로 패턴매칭을 하면, -21억4천3백어쩌구 ~ 21억4천3백어쩌구를 다 커버해야 함!
12.2 Destructing Structs
패턴 매칭의 확장.
#[rustfmt::skip]
fn main() {
let foo = Foo { x: (1, 2), y: 3 };
match foo {
Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"), : x가 첫번쨰는 1, 뒤에는 아무거나
Foo { y: 2, x: i } => println!("y = 2, x = {i:?}"), : y가 2고, x는 아무거나
Foo { y, .. } => println!("y = {y}, other fields were ignored"), : 나머지는 y만 받겠다.
}
근데 위보다는 아래의 형태처럼, Enum 열거체와 패턴 매칭이 찰떡 궁합이다.
위에껀 해석이 필요하므로, 잘 안쓰임;;
12.3 Destructing Enums
*divide_in_two를 보면 리턴이 Result
=> 함수가 잘 작동했는가를 담음. Rust에서 첫 등장한 열거체.
이런식으로 열거체와 쓰이는 형태의 패턴매칭은 매우 많이 쓰임!
12.4 Let Control Flow
패턴매칭은 if문, while문과 같은 거랑 같이 쓰기엔 매우 귀찮음.
Rust에서 제시한 Control Flow를 보자.
fn sleep_for(secs: f32) {
let dur = if let Ok(dur) = std::time::Duration::try_from_secs_f32(secs) { : 결과가 Ok 이면 거기서 dur를 꺼내서 let dur에 담고,
dur
} else {
std::time::Duration::from_millis(500) : 결과가 Err이면 왼쪽을 let dur에 담겠다.
};
std::thread::sleep(dur);
println!("slept for {:?}", dur);
}
이번엔 let, else.
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { : Option.
let s = if let Some(s) = maybe_string { : maybe_string이 String일 경우. 즉, Some일 경우.
s
} else { : maybe_string이 None인 경우.
return Err(String::from("got None"));
};
let first_byte_char = if let Some(first_byte_char) = s.chars().next() {
first_byte_char
} else {
return Err(String::from("got empty string"));
};
if let Some(digit) = first_byte_char.to_digit(16) {
Ok(digit)
} else {
Err(String::from("not a hex digit"))
}
}
Rust에서 Option은, 우리가 수능에서 영단어 공부할 때, 자주 등장하는 단어의 논리라면 별표 다섯개!
Rust의 대부분의 함수의 리턴 타입이 Option이고, 매우 중요.
Option. Rust에서 왜 등장했을까?
컴퓨터의 흑역사를 보면 IEEE 754가 있다.
얘 때문에, 0.1 * 10 = 1.0이 안 됨.
또 하나가 Null임. 이게 악의 근원.
참고로, Null이라는 값을 만든 사람이 있고, 그 사람은 지금 그걸 후회한다 함.
Null은 곧, 존재하지 않는다. 재밌죠?
그럼 undefined와 Null은 뭐가 다를까?
Null은 명시적으로 없다.. 그럼 undefined는 명시적이지 않은 것일까?
일단 이 Null의 "없다" 때문에 생기는게 NullPointException같은 것이다.
그래서, Rust에선 Null이 없다.
근데 생각해보면, 우리가 Null이 없으면 불편할 때가 분명히 있다.
[10, 20, 30] 배열에서 우리가 34를 찾는 함수를 쓰면, 보통은 Null을 반환할 텐데 그게 불가능.
그럼, Null을 쓰기는 싫은데 Nullable함을 나타내야 할 상황이 생기는 것임.
그래서, Option이 나왔다.
Option은 Some(T)와 None으로 나뉜다.
Some은 Null이 아닌 것, None은 원래 쓰이던 Null인 것.
그럼 위의 사례처럼, while의 조건으로 name의 각 값을 pop으로 꺼내올 때,
빈게 있으면 pop이 안되어서 None일 텐데, 그럼 while문이 끝나야 함. Some이 아니므로
위와 같은 형태로 만들 수가 있다.
'RUST 스터디' 카테고리의 다른 글
RUST 스터디[RUST vs C++] 19. Memory Management (1) | 2024.06.18 |
---|---|
RUST 스터디[RUST vs C++] 13. Methods and Traits (1) | 2024.05.15 |
RUST 스터디[RUST vs C++] 10. User-Defined Types (0) | 2024.05.13 |
[RUST vs C++] 17. Standard Library Traits (0) | 2024.05.13 |
[RUST vs C++] 16. 표준 라이브러리 (2) | 2024.05.12 |