홈강좌Rust 입문·중급 47편 중 11편째
Rust 반환값 — 세미콜론 없는 마지막 줄이 돌려주는 값이다
Rust 함수는 -> 타입 으로 돌려줄 값의 타입을 적고, 세미콜론 없는 마지막 줄의 값을 돌려준다. 그 줄에 습관대로 세미콜론을 붙이면 아무 값도 돌려주지 않게 되어 E0308 이 난다. 값을 둘 이상 돌려줄 때는 튜플을 쓴다.
01 세미콜론 하나로 E0308 이 난다
6편의 섭씨→화씨 계산을 함수로 빼 보자. 괄호 뒤의 -> f64 가 "f64 를 돌려준다" 는 뜻이다. 습관대로 계산 줄 끝에 세미콜론을 찍으면 이렇게 된다.
fn to_fahrenheit(c: f64) -> f64 {
c * 9.0 / 5.0 + 32.0;
}
fn main() {
let f = to_fahrenheit(36.5);
println!("{f}");
} Compiling convert v0.1.0 (~/projects/convert)
error[E0308]: mismatched types
--> src/main.rs:1:29
|
1 | fn to_fahrenheit(c: f64) -> f64 {
| ------------- ^^^ expected `f64`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
2 | c * 9.0 / 5.0 + 32.0;
| - help: remove this semicolon to return this value
For more information about this error, try `rustc --explain E0308`.
error: could not compile `convert` (bin "convert") due to 1 previous error- 무엇 — 타입이 안 맞는다(mismatched types).
f64를 돌려준다고 해 놓고(^^^), 실제로는()를 돌려준다.()는 "값 없음" 이다. - 어디 — 함수 이름 아래 줄이 이유를 말한다. 본문에 돌려줄 값이 없어서 "값 없음" 을 돌려주게 됐다(implicitly returns
()). - 고치는 법 — 2번째 줄 끝을
-로 짚고help: remove this semicolon이라고 한다. 세미콜론을 지운다.
02 세미콜론이 있으면 문, 없으면 식
Rust 는 코드 한 줄을 두 가지로 나눈다.
| 문 (statement) | 식 (expression) | |
|---|---|---|
| 끝 | 세미콜론으로 끝난다 | 세미콜론이 없다 |
| 값 | 없다 | 있다 |
| 예 | let x = 5; | 5 + 1 · c * 9.0 / 5.0 + 32.0 |
함수 본문의 마지막 줄이 식이면 그 값이 반환값이 된다. 다른 언어처럼 return 을 쓰지 않아도 된다. 세미콜론을 붙이는 순간 문이 되어 값이 사라진다. 그래서 위 함수가 "값 없음" 을 돌려준 것이다.
세미콜론을 지우면 컴파일되고 값이 나온다.
fn to_fahrenheit(c: f64) -> f64 {
c * 9.0 / 5.0 + 32.0
}
fn main() {
let f = to_fahrenheit(30.0);
println!("{f}");
} Compiling convert v0.1.0 (~/projects/convert)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
Running `target/debug/convert`
8686.0 이 86 으로 찍힌 것은 6편에서 본 대로 .0 을 줄여 찍기 때문이다.
03 중괄호 블록도 값을 낸다
같은 규칙이 함수 밖에서도 통한다. 중괄호 블록(4편)의 마지막 줄이 식이면, 블록 전체가 그 값이 된다.
fn main() {
let total = {
let price = 12000;
let shipping = 3000;
price + shipping
};
println!("{total}");
} Compiling block v0.1.0 (~/projects/block)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.18s
Running `target/debug/block`
15000블록 안에서 price 와 shipping 을 만들고, 세미콜론 없는 마지막 줄 price + shipping 이 블록의 값이 되어 total 에 담겼다. 블록 안의 두 변수는 블록이 끝나면 사라진다. 함수 본문도 사실 이런 블록이다.
04 실습 — 값 둘을 돌려주는 함수
피자 조각을 사람 수로 나눠 한 사람 몫과 남는 조각을 함께 돌려주자. 값이 둘이니 8편의 튜플로 묶는다.
fn split(slices: i32, people: i32) -> (i32, i32) {
(slices / people, slices % people)
}
fn main() {
let (each, left) = split(7, 2);
println!("each: {each}, left: {left}");
} Compiling pizza v0.1.0 (~/projects/pizza)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.19s
Running `target/debug/pizza`
each: 3, left: 1반환 타입 -> (i32, i32) 가 "정수 둘을 묶은 튜플을 돌려준다" 는 뜻이다. 마지막 줄 (slices / people, slices % people) 에 세미콜론이 없으니 이 튜플이 반환값이다. 받는 쪽에서는 let (each, left) = … 로 바로 풀어 담았다.
split(10, 3) 으로 바꿔 돌려 보자. 3 과 1 이 나와야 한다. 다음 편은 조건에 따라 다른 코드를 실행하는 if 다.
05 자주 묻는 질문
return 은 안 쓰나?
쓴다. 함수 중간에서 값을 돌려주고 일찍 끝낼 때 return 값; 을 쓴다. 함수 끝에서 돌려줄 때는 세미콜론 없는 마지막 식을 쓰는 것이 Rust 의 관례다.