let _ = write!(...); 이건 왜 쓰는 거야? 🤔Rust에서 _는 "이 값을 사용하지 않겠다"는 의미입니다.
즉, let _ = write!(...);은 결과 값을 무시하겠다는 의도입니다.
write!()의 반환값은 Result<T, E>write!() 매크로는 std::fmt::Write 트레이트를 사용하며,
이 함수는 반환값으로 Result<(), std::fmt::Error>를 반환합니다.
let result: Result<(), std::fmt::Error> = write!(&mut buf, "{}", self);
write!()가 성공하면 Ok(())를 반환.Err(std::fmt::Error)를 반환.그런데 to_string() 함수에서 write!()의 결과를 굳이 확인할 필요가 없기 때문에,
반환값을 무시하고 싶을 때 _에 담아서 사용하지 않는 것입니다.
write!(); 안 하고 let _ =를 붙일까?Rust는 "사용하지 않는 Result는 반드시 처리해야 한다"는 엄격한 규칙이 있습니다.
즉, 아래처럼 쓰면 컴파일 오류 발생! 🚨
fn to_string(&self) -> String {
let mut buf = String::new();
write!(&mut buf, "{}", self); // ❌ 컴파일러가 경고!
buf
}
warning: unused `Result` that must be used
Rust에서는 Result<T, E> 타입을 반환하는 함수를 호출할 때,
반환값을 반드시 사용하거나 처리해야 합니다.
그런데 write!()의 결과를 확인하지 않으면 컴파일러가 "이거 에러 처리 안 해도 돼?"라고 경고하는 거죠.
let _ =로 해결하는 이유let _ = write!(&mut buf, "{}", self);
_에 결과값을 할당하면 Rust는 "아, 이 값은 일부러 무시하는구나"라고 이해.write!() 실행 가능!let _ = 대신 .expect()를 써도 될까?사실 let _ = 대신 .expect()를 사용하면 에러가 발생했을 때 패닉을 일으킬 수도 있습니다.
write!(&mut buf, "{}", self).expect("Failed to write!");
하지만 write!()가 실패하는 경우는 거의 없기 때문에,
굳이 .expect()를 쓸 필요 없이 let _ =로 무시하는 게 일반적입니다.
| 코드 | 의미 |
|---|---|
write!(&mut buf, "{}", self); | ❌ 컴파일 오류 발생 (반환값을 무시하면 안 됨) |
let _ = write!(&mut buf, "{}", self); | ✅ 반환값을 무시하면서도 컴파일러 경고 방지 |
write!(&mut buf, "{}", self).expect("Error!"); | ✅ 오류 발생 시 패닉을 유발 |
따라서 "에러 처리가 필요 없고, 그냥 무시할 거야!" → let _ = write!(...);가 가장 깔끔한 해결책입니다. 🚀