Rust의 기호(=>, ::, ., -> 등)와 연산자(산술, 비교, 사칙연산자, 논리 연산자, 패턴 매치 연산자 등) 는 종류도 많고 다른 언어와 다른 것도 있어 많이 헷갈리므로 이것에 대해 전체적으로 알아보겠습니다.
Ⅰ. 기호
1. =>
match 문에서 패턴 매핑 결과를 지정할 때 사용합니다.
let num = 2;
match num {
1 => println!("one"),
2 => println!("two"),
_ => println!("other"),
}
위에서 2 => println!(“two”)는 num이 2일 때 실행됩니다.
2. ::
경로(네임스페이스) 구분자. 모듈, 구조체, 열거형, 연관함수, 상수 등에 접근할 때 사용합니다.
let color = Color::Red;
let s = String::from("hello");
Color 열거형의 Red variant, String 타입의 from 연관 함수에 접근합니다.
3. .
필드 접근하거나 메서드를 호출할 때 사용합니다.
let s = String::from("hi");
let len = s.len(); // 메서드 호출
let point = (3, 4);
let x = point.0; // 튜플의 첫 번째 요소
s.len()은 s 객체의 len 메서드를, point.0은 튜플의 첫번째 값을 뜻합니다.
4. ->
함수 또는 클로저의 반환 타입을 지정할 때 사용합니다.
fn add_one(x: i32) -> i32 {
x + 1
}
이 함수는 매개변수 x를 받아 i32 타입으로 결과를 반환합니다.
5. :
변수의 타입을 명시하거나 패턴 매칭에서 사용됩니다.
let score: i32 = 100;
아래는 패턴 매칭에서 :이 사용된 예입니다.
Point { x, y: 0 }에서 y: 0은 y 필드가 정확히 0일 때 매칭됨을 의미합니다.
struct Point { x: i32, y: i32 }
fn main() {
let p = Point { x: 0, y: 7 };
match p {
Point { x, y: 0 } => println!("On the x axis at {x}"),
Point { x: 0, y } => println!("On the y axis at {y}"),
Point { x, y } => println!("On neither axis: ({x}, {y})"),
}
}
6. ;
구문(문장)의 끝을 표시합니다.
let x = 5;
println!("{}", x);
7. ,
목록(튜플, 인수 등)을 구분할 때 사용합니다.
rustlet point = (3, 4);
fn add(x: i32, y: i32) -> i32 { x + y }
8. ..
범위를 표현할 때 사용합니다.
for i in 1..5 {
println!("{}", i); // 1, 2, 3, 4 출력 (5는 포함X)
}
..는 시작값 이상, 끝값 미만의 범위를 의미하며, 끝값을 포함할 때는 ..=으로 사용합니다.
9. &
참조(Reference)를 의미합니다.
let x = 3;
let y = &x;
10. *
역참조(Dereference)를 의미합니다.
let x = 5;
let y = &x;
println!("{}", *y); // y가 참조하는 실제 값(x) 출력
11. @
의미: 패턴 매칭에서 값 바인딩
let v = Some(10);
if let id @ Some(x) = v {
println!("id: {:?}", id);
}
id @ Some(x)는 Some(10) 전체를 id에 바인딩합니다.
Ⅱ. 연산자
1. 산술 연산자
연산자 | 설명 | 예시 | 결과 설명 |
---|---|---|---|
+ | 덧셈 | let a = 10 + 5; | a는 15 |
– | 뺄셈 | let b = 10 – 5; | b는 5 |
* | 곱셈 | let c = 10 * 5; | c는 50 |
/ | 나눗셈 | let d = 10 / 2 | d는 5 |
% | 나머지 | let e = 10 % 3 | e는 1 |
2. 비교(관계) 연산자
연산자 | 설명 | 예시 | 결과 |
---|---|---|---|
== | 같다 | a == b | true 또는 false |
!= | 같지 않다 | a != b | true 또는 false |
> | 크다 | a > b | true 또는 false |
< | 작다 | a < b | true 또는 false |
>= | 크거나 같다 | a >= b | true 또는 false |
<= | 작거나 같다 | a <= b | true 또는 false |
3. 논리 연산자
연산자 | 설명 | 예시 | 결과 |
---|---|---|---|
&& | 논리 AND | (a > 1 ) && (b < 5) | 둘 다 true면 true |
<code>||</code> | 논리 OR | `(a == 1) | |
! | 논리 NOT | !is_valid | true->false, false->true |
4. 비트 연산자
연산자 | 설명 | 예시 | 결과 |
---|---|---|---|
& | 비트 AND | a & b | 각 비트 AND |
<code>|</code> | 비트 OR | `a | b` |
^ | 비트 XOR | a ^ b | 각 비트 XOR |
! | 비트 NOT | !a | 각 비트 반전 |
<< | 왼쪽 시프트 | a << 2 | 비트를 왼쪽 이동 |
>> | 오른쪽 시프트 | a >> 1 | 비트를 오른쪽 이동 |
5. 복합 할당 연산자
연산자 | 설명 | 예시 |
---|---|---|
+= | 더해서 할당 | a +=1; |
-= | 빼서 할당 | b -=2; |
*= | 곱해서 할당 | c *= 3; |
/= | 나눠서 할당 | d /= 2; |
%= | 나머지를 할당 | e %= 4; |
※ Rust는 ++와 –(증가/감소 연산자)를 지원하지 않습니다.
6. 기타 연산자
가. as: 타입 변환
let x: f32 = 10 as f32;
나. 단항 부정 연산자
-a : a의 음수
!a : a의 반전
Ⅲ. 패턴 매칭 관련 연산자 및 문법
match는 여러 패턴에 따라 코드를 분기할 수 있는 핵심 문법으로, C 계열의 switch보다 다양하고 강력한 매칭을 제공합니다.
let value = Some(7);
match value {
Some(x) if x > 5 => println!("greater than five: {}", x),
Some(x) => println!("got: {}", x),
None => println!("no value"),
}
1. | (or 패턴 연산자)
let x = 1;
match x {
1 | 2 => println!("one or two"),
3 => println!("three"),
_ => println!("other"),
}
- 이 예시에서 1 | 2는 x가 1 또는 2일 때 모두 해당 arm을 실행합니다.
2. _ (와일드카드/전부수용 패턴)
모든 값을 의미하며, 사용하지 않을 값을 무시할 때 씁니다.
match some_value {
1 => println!("one"),
_ => println!("other"),
}
3. @ (패턴 바인딩 연산자)
let v = Some(42);
match v {
id @ Some(n) if n > 40 => println!("big! {:?}", id),
_ => println!("other"),
}
- id @ Some(n)은 Some(42) 전체를 id에 바인딩하면서 n 값도 패턴 매칭합니다.
4. if let
특정 패턴만 처리하고 나머지는 무시하고 싶을 때 간결하게 쓸 수 있는 문법입니다.
if let Some(x) = option {
println!("have value: {}", x);
}
5. while let
while let은Rust에서 반복문과 패턴 매칭을 결합해, 어떤 값이 특정 패턴에 계속 일치하는 동안만 루프를 실행하는 구문입니다. 보통 Option, Result, Iterator 등에서 값을 꺼내거나 처리할 때 매우 자주 사용됩니다.
가. Stack처럼 값 꺼내기
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("스택에서 꺼냄: {}", top);
}
- 벡터에서 값을 꺼내는 동작이지만, 동시에 벡터를 스택(LIFO)처럼 쓰는 대표적인 패턴이라 “스택처럼 값 꺼내기”라고 표현한 것입니다.
- stack.pop()이 벡터의 마지막 요소를 꺼내서(Some) 반환합니다. 벡터가 비어 있다면 None을 반환합니다. Vec은 동적 배열이지만, pop은 이를 스택처럼 사용하게 해 줍니다.
- 값이 없을 때 None이 반환되고 루프가 끝납니다.
나. Option을 이용한 카운팅
let mut optional = Some(0);
while let Some(i) = optional {
if i > 9 {
println!("9보다 커서 종료!");
optional = None;
} else {
println!("현재 값: {}", i);
optional = Some(i + 1);
}
}
다. Result 타입, Iterator 등에도 활용
let mut results = vec![Ok(1), Err("Error"), Ok(2)];
while let Some(res) = results.pop() {
match res {
Ok(v) => println!("ok: {}", v),
Err(e) => println!("err: {}", e),
}
}
라. while let, if let, match 비교
구문 | 실용 상황 | 특징와 차이점 |
---|---|---|
while let | 값이 반복적으로 패턴에 매칭될 때 | 패턴 매칭이 실패하면 자동으로 루프 종료 |
if let | 단일 조건만 한 번 검사할 때 | 한 번만 검사, 반복X |
match | 모든 경우의 수를 분기 처리할 때 | 모든 possibility처리, 반복X |