All items of this type can be compared and ordered.
해당 타입에 대한 모든 값이 비교될 수 있다.
All items of this type can be compared and ordered.
해당 타입에 대한 모든 값이 비교될 수 있다.
Some items of this type can be compared and ordered.
PartialEq와 Eq의 관계랑 상당히 밀접함.
'부분적(Partial)'이라는 이름이 붙은 이유는, 타입의 모든 값 쌍에 대해 항상 명확한 순서를 정할 수 없을 수도 있기 때문입니다. 즉, a < b도 아니고 a > b도 아니며 a == b도 아닌 경우가 존재할 수 있습니다.
There's a partial equivalence relation for items of this type—any two items can be definitively compared, but it may not always be true that x==x.
PartialEq 모든 경우에 대해 완벽한 동등성 관계가 성립하지 않을 수 있음을 의미합니다. 수학적으로 동등성 관계는 다음 세 가지 속성을 만족해야 합니다.
반사성 (Reflexive): a == a는 항상 참이다. 대칭성 (Symmetric): a == b가 참이면 b == a도 참이다. 전이성 (Transitive): a == b와 b == c가 모두 참이면 a == c도 참이다.
PartialEq는 대칭성, 전이성을 만족하지만 반사성을 만족 안함.
예시: NaN != NaN
There's an equivalence relation for items of this type—any two items can be definitively compared, and it is always true that x==x.
PartialEq는 Eq의 Super Trait이다. x==x라는 공식을 항상 만족하는 것을 의미한다. 메서드 구현이 아예 없어서 Marker Trait이기도 함.
Expressing loops as iterator transformations can also produce code that is more efficient. In the interests of safety, Rust performs bounds checking on access to contiguous containers such as vectors and slices; an attempt to access a value beyond the bounds of the collection triggers a panic rather than an access to invalid data. An old-style loop that accesses container values (e.g., values[i]) might be subject to these runtime checks, whereas an iterator that produces one value after another is already known to be within range.
iterator 방식을 사용하는 것이 bound checking을 피하기 때문에 효율적이다.
This rich collection of iterator transformations is there to be used. It produces code that is more idiomatic, more compact, and has clearer intent.
풍부한 collection들이 코드들을 이상적이고, 명확적으로 보이도록 만들어준다.
Builds an accumulated value of an arbitrary type by running a closure at each step that takes a mutable reference to some internal state and the current item. This is a slightly different generalization of reduce.
scan은 직접 순회하면서 생성된 값들을 새로운 iteration으로 반환 가능.
Builds an accumulated value of an arbitrary type (not just the Iterator::Item type) by running a closure at each step that takes the value accumulated so far and the current item. This is a generalization of reduce.
임의의 타입에 관해서도 축적이 가능하다.
iterator transforms can be more efficient than an explicit loop, because the compiler can skip the bounds checks it might otherwise need to perform.
예를 들어 Vec<i32>을 순환한다고 가정하면, for 문은 인덱스가 벡터 크기를 벗어났는지 bound checking이 필수적인데, 이터레이터 방식은 이를 하지 않아도 된다.
allowing the whole loop to be expressed as an iterator transform (sometimes also referred to as an iterator adaptor).
iterator로 iterator를 만드는 패턴을 iterator transform이라고 부른다.
<예시> let transformed_numbers: Vec<i32> = numbers .iter() .filter(|&x| x % 2 != 0) .map(|&x| x + 1)
If the underlying type T implements the Copy trait (indicating that a fast bit-for-bit copy produces a valid item; see Item 10), then the Cell<T> type allows interior mutation with less overhead—the get(&self) method copies out the current value, and the set(&self, val) method copies in a new value. The Cell type is used internally by both the Rc and RefCell implementations, for shared tracking of counters that can be mutated without a &mut self.
런타임에 borrow checker를 하기 위해서는 결국 borrow checking을 위한 flag를 이용한 계산을 해야하는데, 단순 복사로 이를 극복했다.
The underlying item is dropped when the strong reference count drops to zero, but the bookkeeping structure is dropped only when the weak reference count also drops to zero.
strong reference가 0이 되면 item이 드랍되고, reference를 담고 있는 structure (i.e., bookkeeping structure)는 weak reference가 0이 되면 드랍된다.
If they were, then it would be possible for some type ConfusedPtr to implement both Deref<TypeA> and Deref<TypeB>, and that would leave the compiler unable to deduce a single unique type for an expression like *x
generic으로 destination type을 지정할 수 없는데, 만약 가능하면 여러 destination type이 생기는 경우가 생기기 때문이다.
error[E0716]: temporary value dropped while borrowed --> src/main.rs:265:19 | 265 | let builder = DetailsBuilder::new( | ___________________^ 266 | | "Robert", 267 | | "Builder", 268 | | time::Date::from_calendar_date(1998, time::Month::November, 28) 269 | | .unwrap(), 270 | | ) | |_____^ creates a temporary value which is freed while still in use 271 | .middle_name("the") 272 | .just_seen(); | - temporary value is freed at the end of this statement 273 | let bob = builder.build(); | --------------- borrow later used here | = note: consider using a `let` binding to create a longer lived value
DetailsBuilder::new 함수가 만든 변수는 만들고, 바로 사라져 버린다. 이 때문에, 후에 builder.build() 함수를 부를 때 문제가 생긴다.
if informal { builder.preferred_name("Bob"); }
소유권이 넘어간 상태로 변수가 소멸되고, 다른 코드 부분에서 소유권이 넘어간 변수를 사용하니, 컴파일 에러가 발생한다.
This boilerplate code is also brittle, in the sense that a future change that adds a new field to the struct requires an update to every place that builds the structure.
이러한 보일러플레이트 코드는 다루기 힘든데, 새로운 필드가 추가되면 모든 장소의 코드를 업데이트해줘야 하기 때문이다.
Rust insists that all fields in a struct must be filled in when a new instance of that struct is created. This keeps the code safe by ensuring that there are never any uninitialized values but does lead to more verbose boilerplate code than is ideal.
struct의 모든 필드 값이 초기화 되는 것을 강제하고 있다. 이는 코드 안정성을 보장하지만 장황한 보일러플레이트 코드를 유발한다.