Rust 튜플
튜플(tuple)은 타입이 서로 다를 수도 있는 여러 값을 하나로 묶어요. 새로운 타입을 따로 정의하지 않고도 관련된 값들을 빠르게 묶을 수 있는 방법이에요.
튜플 만들기
섹션 제목: “튜플 만들기”fn main() { let person: (&str, i32, bool) = ("지민", 30, true); println!("{:?}", person);}실행 결과:
("지민", 30, true)이 튜플은 &str, i32, bool을 하나의 값에 섞어 담고 있어요. 배열은 이렇게 할 수 없어요. 배열의 모든 요소는 같은 타입이어야 하거든요.
튜플 전체를 출력하려면 {} 대신 {:?}(디버그 형식)를 쓰세요. 그냥 {}로는 튜플을 출력할 수 없어요.
위치로 요소에 접근하기
섹션 제목: “위치로 요소에 접근하기”.0, .1, .2처럼 써요. 튜플의 위치는 0부터 시작해요.
fn main() { let person = ("지민", 30, true);
println!("이름: {}", person.0); println!("나이: {}", person.1); println!("활성: {}", person.2);}실행 결과:
이름: 지민나이: 30활성: true위치는 코드에 직접 적은 숫자여야 해요. person.i처럼 변수를 쓸 수는 없어요. 위치마다 타입이 다를 수 있는데, Rust는 컴파일할 때 타입을 알아야 하기 때문이에요.
튜플 구조 분해하기
섹션 제목: “튜플 구조 분해하기”모든 값을 한 줄에 각각의 변수로 꺼낼 수 있어요. 이걸 구조 분해(destructuring)라고 해요.
fn main() { let person = ("지민", 30, true); let (name, age, is_active) = person;
println!("{name}, {age}살, 활성: {is_active}");}실행 결과:
지민, 30살, 활성: true.0, .1, .2로 계속 접근하는 것보다 이쪽이 더 읽기 쉬운 경우가 많아요. 특히 튜플의 필드가 두세 개를 넘어가면 더 그래요.
함수에서 여러 값 반환하기
섹션 제목: “함수에서 여러 값 반환하기”함수는 반환 타입을 하나만 선언할 수 있어서, 값을 여러 개 돌려주고 싶을 때는 튜플을 쓰는 게 자연스러워요.
fn min_max(numbers: &[i32]) -> (i32, i32) { let min = *numbers.iter().min().unwrap(); let max = *numbers.iter().max().unwrap(); (min, max)}
fn main() { let (smallest, largest) = min_max(&[4, 8, 1, 9, 3]); println!("최솟값: {smallest}, 최댓값: {largest}");}실행 결과:
최솟값: 1, 최댓값: 9&[i32], .iter(), .unwrap()은 아직 신경 쓰지 않아도 돼요. 슬라이스, 반복자, Option 페이지에서 다뤄요. 여기서 눈여겨볼 부분은 반환 타입 (i32, i32)와, main이 그 값을 곧바로 두 변수로 구조 분해하는 모습이에요.
튜플 바꾸기와 값 맞바꾸기
섹션 제목: “튜플 바꾸기와 값 맞바꾸기”튜플을 mut로 선언하면 같은 .0, .1 위치를 이용해서 필드를 하나씩 바꿀 수 있어요. 값은 바꿀 수 있지만 모양은 바꿀 수 없어요. 튜플은 처음 만들었을 때의 필드 개수와 타입을 항상 그대로 유지해요.
구조 분해는 반대 방향으로도 동작해요. 이미 있는 변수에 값을 대입할 수도 있어요. 그러면 임시 변수 없이 한 줄로 두 값을 맞바꿀 수 있어요. 필드 중 일부만 필요하다면, 필요 없는 자리에는 _를 쓰세요.
fn main() { let mut point = (3, 4); point.0 += 10; // 필드 하나만 그 자리에서 바꿔요 println!("point = {:?}", point);
let mut a = 1; let mut b = 2; (a, b) = (b, a); // 두 값을 맞바꿔요 println!("a = {a}, b = {b}");
let (x, _) = point; // x만 남기고 두 번째 필드는 무시해요 println!("x = {x}");}실행 결과:
point = (13, 4)a = 2, b = 1x = 13맞바꾸기가 동작하는 이유는 Rust가 오른쪽의 (b, a)를 먼저 만들기 때문이에요. 그다음에야 그 값을 a와 b에 풀어 넣어요. _와 패턴으로 할 수 있는 일은 패턴 매칭 페이지에 훨씬 많이 나와요.
빈 튜플: ()
섹션 제목: “빈 튜플: ()”사실 여러분은 모르는 사이에 이미 튜플을 하나 만났어요. ()는 유닛 타입(unit type)이라고 불러요. 함수가 의미 있는 값을 돌려주지 않을 때 반환하는 게 바로 이 타입이에요. fn main()의 반환 타입도 생략되어 있을 뿐 ()예요.
튜플과 구조체, 언제 무엇을 쓸까요
섹션 제목: “튜플과 구조체, 언제 무엇을 쓸까요”튜플은 이름 없이 빠르게 값을 묶을 때 좋아요. 특히 함수에서 값 두세 개를 돌려줄 때 좋아요. 하지만 값의 묶음이 이름 붙은 필드를 가진 실제 개념을 나타낸다면(예를 들어 코드 곳곳에서 이름으로 부를 이름과 나이를 가진 Person), 보통은 구조체가 더 좋고 읽기 쉬운 선택이에요.
연습 문제
섹션 제목: “연습 문제”1. 합과 곱
섹션 제목: “1. 합과 곱”두 숫자의 합과 곱을 함께 돌려주는 함수 sum_and_product(a: i32, b: i32) -> (i32, i32)를 작성하세요. main에서 5와 6으로 호출하고 결과를 구조 분해해 보세요. 힌트: 함수의 마지막 줄은 튜플 자체인 (a + b, a * b)이고, 세미콜론은 없어요.
정답 보기
fn sum_and_product(a: i32, b: i32) -> (i32, i32) { (a + b, a * b)}
fn main() { let (sum, product) = sum_and_product(5, 6); println!("합 = {sum}, 곱 = {product}");}실행 결과:
합 = 11, 곱 = 302. 두 꼭짓점으로 만든 직사각형
섹션 제목: “2. 두 꼭짓점으로 만든 직사각형”직사각형은 두 점의 튜플로 저장할 수 있어요. 각 점도 튜플이에요: let rect = ((1, 2), (5, 5));. 이 직사각형의 너비, 높이, 넓이를 구해 보세요. 힌트: 튜플은 중첩할 수 있고, rect.1.0은 “두 번째 점의 첫 번째 필드”라는 뜻이에요.
정답 보기
fn main() { let rect = ((1, 2), (5, 5));
let width = rect.1.0 - rect.0.0; let height = rect.1.1 - rect.0.1;
println!("너비 {width}, 높이 {height}, 넓이 {}", width * height);}실행 결과:
너비 4, 높이 3, 넓이 12두 점을 한꺼번에 구조 분해할 수도 있어요: let ((x1, y1), (x2, y2)) = rect;. 타이핑할 건 늘어나지만, rect.1.0 - rect.0.0보다 x2 - x1이 읽기 쉬워요. 이렇게 점이 줄줄이 쌓이기 시작하면, 이름 붙은 필드를 가진 구조체가 더 명확하다는 신호예요.
- 튜플은 타입이 서로 다를 수 있는 값들을 묶어요:
(name, age, is_active). - 필드는
.0,.1,.2로 접근하거나, 구조 분해로 한꺼번에 꺼내요. - 튜플은 함수에서 여러 값을 돌려주는 자연스러운 방법이에요.
mut튜플의 필드는 바꿀 수 있지만, 크기와 타입은 바꿀 수 없어요.(a, b) = (b, a);로 두 값을 맞바꿀 수 있어요.- 이름이 붙고 여러 번 다시 쓰는 묶음이라면 구조체를 쓰세요.
이해도 점검
섹션 제목: “이해도 점검”이해도 점검
1. 배열은 못 하는데 튜플은 담을 수 있는 것은 무엇일까요?
2. person이라는 튜플의 두 번째 요소에는 어떻게 접근할까요?
3. let mut a = 1; let mut b = 2; (a, b) = (b, a); 다음에 a와 b는 각각 얼마일까요?
점수: 0 / 3
더 알아보기
섹션 제목: “더 알아보기”- 튜플 타입 — The Rust Programming Language 한국어판: 튜플을 만들고, 구조 분해하고, 인덱스로 접근하는 방법을 소개하는 공식 입문서예요.
- Tuples — Rust by Example (영어): 중첩된 튜플, 함수 인자로 쓰는 튜플 예제를 실행해 볼 수 있어요.
tuple타입 — 표준 라이브러리 문서 (영어): 비교, 복사,{:?}출력처럼 튜플이 지원하는 트레이트를 정리해 두었어요.unit타입 — 표준 라이브러리 문서 (영어):()가 무엇이고 어디에 나타나는지 설명해요.- Destructuring assignments — The Rust Reference (영어):
(a, b) = (b, a);뒤에 있는 정확한 규칙이에요.