테스트케이스: 리스트
각 요소를 순차적으로 처리해야 하는 구조체에 대해 fmt::Display를 구현하는 것은 까다롭습니다. 문제는 각 write!가 fmt::Result를 생성한다는 것입니다. 이를 적절히 처리하려면 모든 결과를 다뤄야 합니다. Rust는 정확히 이 목적을 위해 ? 연산자를 제공합니다.
write!에 ?를 사용하는 것은 다음과 같습니다:
// `write!`가 에러를 발생시키는지 확인합니다. 에러가 발생하면
// 에러를 반환합니다. 그렇지 않으면 계속 진행합니다.
write!(f, "{}", value)?;
?가 사용 가능해지면 Vec에 대한 fmt::Display 구현은 간단해집니다:
use std::fmt; // `fmt` 모듈을 가져옵니다.
// `Vec`을 포함하는 `List`라는 이름의 구조체를 정의합니다.
struct List(Vec<i32>);
impl fmt::Display for List {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 튜플 인덱싱을 사용하여 값을 추출하고,
// `vec`에 대한 참조를 생성합니다.
let vec = &self.0;
write!(f, "[")?;
// `vec`의 `v`를 순회하면서 반복 인덱스를 `index`에 열거합니다.
for (index, v) in vec.iter().enumerate() {
// 첫 번째를 제외한 모든 요소에 콤마를 추가합니다.
// 에러 시 반환하기 위해 ? 연산자를 사용합니다.
if index != 0 { write!(f, ", ")?; }
write!(f, "{}", v)?;
}
// 열려 있는 대괄호를 닫고 `fmt::Result` 값을 반환합니다.
write!(f, "]")
}
}
fn main() {
let v = List(vec![1, 2, 3]);
println!("{}", v);
}
실습
벡터의 각 요소의 인덱스도 출력되도록 프로그램을 변경해 보세요. 새로운 출력은 다음과 같아야 합니다:
[0: 1, 1: 2, 2: 3]