Open9
「Learn Rust With Entirely Too Many Linked Lists」を読んだ記録
Rustが好きと書いておきながら、「Learn Rust With Entirely Too Many Linked Lists」を知らなかったので読んでみます。これはその記録です。
「1. Introduction」では連結リストの使いどころって少ないはずというのを訴えている様子(正しく読めていれば)。
-
std::boxed
に書いてある連結リストの実装だと、分割・結合時に無駄が生じる- 最後の要素に、次が
List::Empty
であることを示さなければいけない -
List::Empty
もList
型と同じ大きさを持ってしまう
- 最後の要素に、次が
- 0か0でないかという持ち方をすればnullポインタ最適化が行われて嬉しい
- そのために、データは連結リストの外側で持ったほうが良い
-
std::mem::replace
を使うことで一時的なmove
を避けることができる - 自動的に実装される
Drop
だとBox
の都合で末尾再帰にできないため、先頭から順にLink::Empty
に置き換える必要がある
「3. An Ok Stack」はOption
を使うようになったのとイテレータの実装。IntoIterator
の実装にIntoIter
を使ったのはIter
とかIterMut
と合わせるため?
-
std::rc::Rc
でも最後の参照であればOption::take
と同様のことができる
「5. A Bad but Safe Doubly-Linked Deque」
- 要素を追加するたびに参照カウンタが2つ増えてしまう
-
std::rc::RefCell
からimmutable referenceがほしいとき、その型は&T
ではなくRef<T>
となる - この方法だと
Iterator
の実装ができない
- "pop"した際に必ず
tail
の指す先も変えないといけないが、それはunsafe
でプログラマが責任を負うしかない -
miri
を使えばunsafe
なコードをある程度チェックしてくれる
- "pop"した際に必ず
tail
の指す先も変えないといけないが、それはunsafe
でプログラマが責任を負うしかない -
miri
を使えばunsafe
なコードをある程度チェックしてくれる
「7. A Production Unsafe Deque」
- "Variance"という概念がある(正直難しくてよくわからない)
- この記事が参考になりそう
- "covariant"にしたいが
*mut T
を持つ構造体は"invariant"になってしまう -
std::ptr::NonNull
は生のポインタを*const T
として持っているため"covariant" -
unsafe
なコードを書くときはpanic!
時の挙動にも気を使う必要がある-
debug_assert!
によってpanic!
になりうる箇所が増えるのはむしろ危険なことがある
-
- コレクション系で
std::hash::Hash
を実装するときは、len
もハッシュ値の計算に用いないと、区切り方が異なるコレクションでも同じハッシュ値となってしまう