2022년 09주차 기록
2022.02.28
rust
02/28 (월) ~ 03/06 (일)
Rust 공부
- 2022-03-02 현재 Learn Rust 진행중
- 종종 까먹는데 이름다음에
!
가 붙으면 macro라는 뜻이다
Formatted print 섹션
- traits ? :
특성
으로 번역됨- 관련 문서 : Formatting traits
- text 의 display를 관리하는 method
- print 문에서 문자열 내에서
{:b}
형태로 표현되는 것은marker
이고 -
{:b}
의 display는fmt::Binary
trait 에서 관리하게된다
- 기본적으로 중요한 두가지 traits는 아래와 같다
-
fmt::Debug
:{:?}
marker를 사용하며, 디버깅 목적으로 text를 format한다 -
fmt::Display
:{}
marker를 사용하며, 사용자 친화적인 방식으로 text를 format한다
-
Debug
- 관련 문서 : Debug
-
std::fmt
의 formattingtraits
를 사용하려는 모든 type들은 프린트가능해지려면 구현이 필요하다 - 자동적인 implementation은
std
library에 있는 type들에 대해서만 제공된다 - 모든 다른 type들은 수동적으로 구현되어야 한다
-
fmt::Debug
trait는 이것을 매우 직관적으로 만든다 - 모든 types는
fmt::Debug
의 implementation 은 파생(drive, 즉 automatically create) 할 수있다- 반면에
fmt::Display
의 경우는 수동적으로 구현되어야 한다
- 반면에
-
fmt::Debug
는 모든 것을 printable하게 만들수는 있지만 어떻게 보여줄지에 대한 조정은 할 수 없다
Display
- 관련 문서 : Display
-
fmt::Debug
는 컴팩트하고 깔끔하게 보이지 않기에, 출력모양을 조정하는 것이 좋다 - 이것은
fmt::Display
를 수동적으로 구현함으로써 가능하다 - 구현하면 아래처럼 된다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 'use'를 통해서, 'fmt' 모듈을 import 해서 'fmt' 모듈 사용이 가능해진다 use std::fmt; // 'fmt::Display'가 구현될 structure를 정의한다. // 이건 'Structure'로 이름붙은 tuple 구조체로 'i32'를 포함한다 struct Structure(i32); // '{}' marker를 사용하기 위해, 위 type에 대해 'fmt::Display' trait 가 직접 구현되어야 한다 impl fmt::Display for Structure { // 이 trait는 정확한 함수 signature 로 정의되는 'fmt' method가 필요하다 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // 제공받은 출력 스트림 'f'에 첫번째 element를 정확히 작성한다 // operation의 성공이나 실패를 표시하는 'fmt::Result'를 반환한다 // 'write!'가 'println!'과 매우 유사한 문법을 사용하고 있음을 주목하라 write!(f, "{}", self.0); }
-
fmt::Display
는fmt::Debug
보다 명확하겠지만,std
library에 문제를 제공한다- 모호한 type들은 어떻게 표시되는가?
- 예를 들면,
std
library가 모든Vec<T>
에 대해 single style을 구현했다면, 어떤 style을 가져야 하나? - 아래 두가지중 하나가 될까?
-
Vec<path>
:/:/etc:/home/username:/bin
(split on:
) -
Vec<number>
:1,2,3
(split on,
)
-
- 아니다. 모든 type에 이상적인 style은 없고
std
library는 하나를 지시한다고 가정하지 않는다 -
fmt::Display
는Vec<T>
나 다른 일반적인 container에 대해 구현되지 않았다. - 이런 일반적인 case들에 대해서는
fmt::Debug
가 사용되어야 한다 - 그렇지만 이건 문제점이 아니다.
- 일반적이지 않은 새로운 container type에대해
fmt::Display
가 구현될 수 있기 때문이다 -
(역자주) 변수를 container라는 용어로 부르고 있다. 색다르네..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
use std::fmt; // Import 'fmt' // 두개의 숫자를 갖는 구조체이다. // 결과물이 'Display'와 대조되도록 'Debug'에서 파생시킨다 #[derive(Debug)] struct MinMax(i64, i64); // 'MinMax'에 대한 'Display'를 구현한다 impl fmt::Display for MinMax { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // 각각의 위치기반 데이타 포인트를 참조하도록 'self.숫자' 형식을 사용한다 wirte!(f, "({}, {})", self.0, self.1) } } // 비교를 위해 필드들에 이름을 부여할수 있는 구조체를 정의한다 #[derive(Debug)] sturct Point2D { x: f64; y: f64; } // 비슷하게 'Point2D'를 위한 'Display'를 구현한다 impl fmt::Display for Point2D { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // 'x'와 'y'만 표시되도록 지정한다 wirte!(f, "x: {}, y: {}", self.x, self.y) } } fn main() { let minmax = MinMax(0, 14); println!("Compare structures:"); println!("Display: {}", minmax); println!("Debug: {:?}", minmax); let big_range = MinMax(-300, 300); let small_range = MinMax(-3, 3); println!("The big range is {big} and the small is {small}", small = small_range, bing = big_range); let point = Point2D { x: 3.3, y: 7.2 }; println!("Compare points:"); println!("Display: {}", point); println!("Debug: {:?}", point); // 에러가 발생한다. 'Debug' 와 'Display'가 모두 구현되었으나, // '{:b}'의 사용은 'fmt::Binary'가 구현을 요구한다. 아래 줄은 동작하지 않을것이다 // println!("What does Point2D look like in binary: {:b}?", point); }
- 위와 같이,
fmt::Display
가 구현되었지만fmt::Binary
는 구현되지 않았기에 사용할 수 없다. -
std::fmt
는 이런traits
를 많이 가지고 있고 각자의 구현을 요구한다. -
std::fmt
에 더 자세한 내용이 있다
- 일반적이지 않은 새로운 container type에대해