04–05. 제어 흐름 · 함수·표현식·반환값·문서화 주석
Rust 의 if 는 표현식입니다. let x = if cond { 1 } else { 2 } 처럼 값을 만들 수 있습니다. loop / while / for 의 차이, 그리고 Rust 특유의 break 에 값 붙이기, 라벨 붙은 break/continue, 그리고 range 와 iterator 의 for 루프 동작까지 한 번에 다룹니다. 함수 정의 fn name(arg: T) -> R { ... }, 표현식과 문장(statement vs expression) 의 구분, 명시적 return 과 마지막 표현식의 암묵적 반환, 그리고 `///` 문서화 주석으로 cargo doc 이 생성되는 흐름까지 다룹니다. Rust 의 함수형 스타일 작성을 시작하는 강의입니다.
이 강의에서 배우는 것
- 1if 가 표현식임을 이해하고 값으로 사용한다
- 2loop / while / for 의 적절한 쓰임을 구분한다
- 3break 에 값을 붙여 loop 의 결과로 반환한다
- 4라벨로 중첩 루프를 정확히 빠져나간다
- 5range(`0..10`, `0..=10`) 와 iterator 의 for 루프를 사용한다
- 6fn 으로 함수를 정의하고 인자·반환 타입을 명시한다
- 7표현식과 문장의 차이를 안다
- 8명시적 return 없이 마지막 표현식으로 값을 반환한다
- 9/// 문서화 주석을 작성하고 cargo doc 으로 HTML 을 만든다
- 10튜플 반환으로 다중 값을 돌려준다
04. 제어 흐름 (if·loop·while·for·break value)
Rust 의 if 는 표현식입니다. let x = if cond { 1 } else { 2 } 처럼 값을 만들 수 있습니다. loop / while / for 의 차이, 그리고 Rust 특유의 break 에 값 붙이기, 라벨 붙은 break/continue, 그리고 range 와 iterator 의 for 루프 동작까지 한 번에 다룹니다.
소개
Rust 에는 삼항 연산자 `cond ? a : b` 가 없습니다. 대신 if 자체가 값을 만드는 표현식이라 자연스럽게 같은 표현이 가능합니다. 이런 일관성이 코드를 짧고 읽기 쉽게 만들어 줍니다.
핵심 개념
1) if 는 표현식
let n = 10;
let kind = if n % 2 == 0 { "짝수" } else { "홀수" };
println!("{}", kind); // 짝수각 분기의 타입이 같아야 합니다. 한 쪽이 "짝" 다른 쪽이 42 면 컴파일 에러.
2) loop — 무조건 반복, break 로 빠져나옴
- 조건이 없는 무한 루프
- break 에 값을 붙이면 loop 의 평가값이 됨
- 라벨(`'outer:`) 로 중첩 루프 제어
3) while — 조건이 true 인 동안
조건이 처음부터 false 면 한 번도 실행 안 됨. 인덱스 기반 순회보단 for 가 자주 쓰입니다.
4) for — iterator 순회
- `for x in 0..10` — 0,1,...,9 (배타적 우측)
- `for x in 0..=10` — 0,1,...,10 (포괄)
- `for x in &v` — Vec 등 iterator 순회
핵심 예제
break 에 값을 붙이는 패턴 — 검색에 유용:
fn main() {
let arr = [3, 7, 11, 13, 17];
let target = 11;
let idx = loop {
let mut i = 0;
while i < arr.len() {
if arr[i] == target { break i as i32; }
i += 1;
}
break -1;
};
println!("index = {}", idx); // 2
}라벨로 중첩 루프 빠져나가기:
fn main() {
'outer: for i in 0..5 {
for j in 0..5 {
if i + j == 6 {
println!("found ({}, {})", i, j);
break 'outer;
}
}
}
}for 와 range/iterator:
fn main() {
for i in 0..3 { println!("i={}", i); } // 0,1,2
for i in 1..=3 { println!("j={}", i); } // 1,2,3
let v = vec![10, 20, 30];
for x in &v { println!("x={}", x); }
for (idx, x) in v.iter().enumerate() {
println!("{}-{}", idx, x);
}
}자주 하는 실수
Q. for i = 0; i < n; i++ 같은 C 스타일 for 는?
A. Rust 에는 없습니다. `for i in 0..n` 으로 충분하고, 인덱스를 같이 쓰려면 `.iter().enumerate()`. 더 표현력 있고 off-by-one 실수가 줄어듭니다.
Q. if 의 분기 타입이 다르면 어떻게 되나요?
A. 컴파일 에러. let x = if cond { 1 } else { "two" } 는 안 됩니다. 같은 타입으로 맞추거나, 둘 다 어떤 enum 안에 감싸야 합니다.
Q. while let 은 뭔가요?
A. 패턴 매칭이 가능한 while. `while let Some(v) = iter.next() { ... }` 처럼 Option 이 Some 인 동안 반복. 패턴 매칭 강의에서 자세히.
정리
- if 는 표현식 → let 의 우변으로 사용 가능
- loop 는 무한, break 로 값 반환 가능
- for in range / for in iterator 가 가장 자주 쓰이는 형태
- 중첩 루프는 라벨로 정확히 빠져나간다
과제
- 1 부터 100 까지 짝수만 더한 값을 for 와 if 로 구해 출력
- loop + break with value 패턴으로 sqrt(2) 의 근사값을 뉴턴법으로 5회 반복 계산
- 2차원 좌표 (i, j) 에서 i + j 가 처음으로 7이 되는 지점을 라벨 break 로 찾기
05. 함수·표현식·반환값·문서화 주석
함수 정의 fn name(arg: T) -> R { ... }, 표현식과 문장(statement vs expression) 의 구분, 명시적 return 과 마지막 표현식의 암묵적 반환, 그리고 `///` 문서화 주석으로 cargo doc 이 생성되는 흐름까지 다룹니다. Rust 의 함수형 스타일 작성을 시작하는 강의입니다.
소개
Rust 의 함수는 단순하지만, 표현식 중심 언어라는 특성 때문에 다른 언어에서 온 사람이 처음엔 헷갈리는 지점이 하나 있습니다 — **마지막 줄에 세미콜론을 붙이느냐 마느냐** 가 반환값 유무를 결정합니다. 이 한 규칙만 익히면 코드가 훨씬 짧아집니다.
핵심 개념
1) 함수 기본 문법
fn add(a: i32, b: i32) -> i32 {
a + b // 세미콜론 없음 → 반환 값
}2) 표현식 vs 문장
- **표현식(expression)** — 값을 만드는 것. `5`, `a + b`, `if cond { 1 } else { 2 }`, 블록 `{ let x = 1; x + 1 }`
- **문장(statement)** — 동작은 하지만 값은 만들지 않는 것. `let x = 5;`, `fn f() {}`
- 표현식에 세미콜론을 붙이면 문장이 됨 → 값이 사라짐
3) 명시적 return
조기 종료가 필요할 때 `return value;` 사용. 일반적으로는 마지막 표현식이 더 idiomatic.
4) 문서화 주석
- `///` 으로 시작하면 다음 항목에 대한 문서 주석
- Markdown 지원 — 코드 예제는 자동 doctest 가 됨
- `cargo doc --open` 으로 HTML 문서 생성·열기
핵심 예제
암묵적 반환과 명시적 return:
fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
return -1; // 조기 종료
}
a / b // 마지막 표현식 → 반환
}
fn main() {
println!("{}", divide(10, 3)); // 3
println!("{}", divide(10, 0)); // -1
}튜플 반환으로 다중 값:
fn minmax(v: &[i32]) -> (i32, i32) {
let mut mn = v[0];
let mut mx = v[0];
for &x in v {
if x < mn { mn = x; }
if x > mx { mx = x; }
}
(mn, mx)
}
fn main() {
let (a, b) = minmax(&[3, 7, 1, 9, 4]);
println!("min={}, max={}", a, b); // 1, 9
}문서화 주석 — Markdown + doctest:
/// 두 수를 더해 반환합니다.
///
/// # 예제
///
/// ```
/// assert_eq!(my_crate::add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}cargo doc --open # HTML 문서 생성
cargo test --doc # doctest 실행자주 하는 실수
Q. 반환값이 안 나가요. 분명히 `a + b` 라고 썼는데
A. `a + b;` 처럼 세미콜론을 붙이면 문장이 돼서 값이 사라집니다. 마지막 줄은 세미콜론 없이.
Q. unit 타입 `()` 가 뭔가요?
A. 다른 언어의 void 비슷합니다. 반환 타입 생략 = `-> ()`. 함수가 의미 있는 값을 안 돌려준다는 뜻.
Q. main 함수는 반환값을 못 가지나요?
A. `fn main() -> Result<(), Box<dyn Error>>` 처럼 Result 를 반환하면 ? 연산자도 main 에서 쓸 수 있습니다. 에러 처리 강의에서 자세히.
정리
- 함수 시그니처는 인자·반환 타입을 모두 명시
- 마지막 표현식이 반환값, 세미콜론 붙이면 사라짐
- 조기 종료에 return 사용
- /// 로 작성한 주석은 cargo doc 으로 HTML 문서가 되고 doctest 도 실행됨
과제
- 섭씨 ↔ 화씨 변환 함수 두 개를 작성하고 main 에서 호출
- 최소·최대·평균을 한 번에 돌려주는 stats 함수를 (i32, i32, f64) 튜플로 반환하게 작성
- /// 주석에 예제 코드를 넣고 `cargo test --doc` 으로 doctest 통과 확인
댓글 0
아직 댓글이 없습니다. 첫 댓글을 남겨 주세요.
댓글은 회원만 쓸 수 있습니다.
광고·욕설·비방·개인정보·불법 내용이 담긴 댓글은 숨기거나 지웁니다. 댓글은 닉네임과 함께 공개됩니다. 개인정보처리방침