getやnext。よく考えると所有権ムーブする系としない系がある。
これまで
取得系メソッドのインタフェースは以下を想定していた。
impl<T> LinkedList<T> { pub fn get(&mut self, index: u32) -> &mut T { return &mut self.head.as_mut().unwrap().item; } pub fn next(&mut self) -> &mut T { return &mut self.head.as_mut().unwrap().item; } }
要件
でも、よく考えたら、以下のような要件があった。
- 所有権をムーブしたいときと、したくないときがある
- 全体からある位置にある要素をひとつだけ取得したいときと、ひとつずつすべて取得したいときがある
- 配列のように
list[index]という糖衣構文を実装したい(list.as_mut_from_index(index);とかは嫌)
| 所有権ムーブ | 取得対象 |
|---|---|
| する | 1個のみ |
| する | すべて(1個ずつ) |
| しない | 1個のみ |
| しない | すべて(1個ずつ) |
調査
- rustのIteratorの実装
- std::iter::Iteratorトレイト
- nextメソッド
以下のようなメソッドが欲しい、のか?
| 所有権ムーブ | 取得対象 | メソッド |
|---|---|---|
| する | 1個のみ | next() |
| する | すべて(1個ずつ) | into_iter() |
| しない | 1個のみ | as_ref_from_index(), as_mut_from_index() |
| しない | すべて(1個ずつ) | iter(), iter_mut() |
上から3番目が微妙。他の3つは標準モジュールにトレイトがあったり、それっぽいメソッド名があったりする。でも、上から3番目のやつはlist[0]、list[0] = 1みたいな記法でやるほうがスッキリできると思う。演算子のオーバーライトで実装するのだろうか? 調査が大変そうなので後回し。
方針
std::iter::Iteratorトレイトを実装すれば、into_iter()もついてくるらしい。これで所有権を奪うイテレータは実装完了になる、と思う。
2番目、iter(), iter_mut()。これらは所有権を奪わずに不変参照・可変参照を返す。
3番目、next()の参照版。next_ref(), next_mut()みたいなメソッドを持つトレイトは見つけられなかった。
4番目、get_ref_from_index(i32), get_mut_from_index(i32)みたいな指定した位置にある要素の参照を返すメソッドが欲しい。だが、そんなトレイトは見つからない。これらメソッドは順序をもった配列系の構造には求められると思うのだが。いや、list[0], list[0] = 1のような記法のオーバーライドで代用するのか? それ、どうやってやるの?
結論
とりあえずstd::iter::Iteratorトレイトのnextを実装しよう。
展望
それをやれば他のメソッドもついてくるらしい。たとえばinto_iter()。所有権を奪ってイテレータを返すメソッド。イテレータにはfilterなどの極めて有用なメソッドが多数あるっぽい。まだよく知らない。少しずつ調べていこう。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- rustc 1.34.2 (6c2484dc3 2019-05-13)
- cargo 1.34.0 (6789d8a0a 2019-04-01)
$ uname -a Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux