我目前正在看Rust Sokoban教程,一邊輸入代碼一邊玩,看看我如何在不破壞它的情況下 "改進 "它。 在推箱子一章中,他們引入了兩個 "標記組件 "來 "告訴我們哪些物體可以移動,哪些不可以":
#[derive(Component, Default)]
#[storage(NullStorage)]
pub struct Movable;
#[derive(Component, Default)]
#[storage(NullStorage)]
pub struct Immovable。
之后,我們有以下代碼:
let mutmov: HashMap<(u8, u8), Index> = (&entities, &movables, &position)
.join()
.map(|t|((t.2.x, t. 2.y), t.0.id())
.collect::<HashMap<_, _>>()。
let mutimmov: HashMap<(u8, u8), Index> = (&entities, &immovables, &position)
.join()
.map(|t|((t.2.x, t. 2.y), t.0.id())
.collect::<HashMap<_, _>>()。
其中&entities是Entities的一個實體,&poss是WriteStorage<Position>的一個實體,而& movables和&immovables分別是ReadStorage<'a, Movable>和ReadStorage<'a, Immovable>的實體。
作為一個對 DRY 代碼很神經質的人,上面的兩個函式真的讓我很頭疼,我覺得有必要重構一下,但是我還沒能想出如何組成一個函式來處理 &movables 和 &immovables 的不同型別。
例如,如果我嘗試這個函式:
fn collect<T>(entities: & Entities, storable: & ReadStorage< T>, positions: & WriteStorage< Position> )
-> HashMap<(u8, u8), Index> {
(&物體,&可存盤,&位置)
.join()
.map(|t|((t.2.x, t. 2.y), t.0.id())
.collect::<HashMap<_, _> >()
}
并且像這樣呼叫它:
let mov: HashMap<(u8, u8), Index> = collect(&entities, &movables, &position);
或者像:
let mov: HashMap<(u8, u8), Index> = collect::<Movable>(&entities, &movables, &poss);
......編譯失敗的原因是:
error[E0277]: the trait bound
T: specs::Componentis not satisfied
。 --> src esourcesinput_system.rs:95:46 | 95 | fn collect(entities: &Entities, storable: & ReadStorage, positions: & WriteStorage) | ^^^^^^^^^^^^^^^specs::Component的特性沒有為T實作。 | ::: C:UsersBrianKessler.cargo egistrysrcgithub.com-1ecc6299db9ec823specs-0.17.0srcstoragemod.rs:143:29 | 143 | pub struct MaskedStorage<T: Component> { | --------- 在MaskedStorage中此系結所需的。 | 幫助:考慮限制型別引數T。 | 95 | fn collect<T: specs::Component>(entities: &Entities, storable: &ReadStorage, positions: & WriteStorage) | ^^^^^^^^^^^^^^^^^^錯誤:由于之前的錯誤而中止
。關于這個錯誤的更多資訊,請嘗試
rustc --explain E0277。 error: could not compilerust-sokoban>要了解更多,請用 --verbose 再次運行該命令。
例如,如果我嘗試這個函式(按照 @AlexeyLarionov 的建議):
fn collect<T。specs::Component>(entities: &Entities, storable: &ReadStorage<T>, positions: &WriteStorage<Position> )
-> HashMap<(u8, u8), Index> {
(&物體,&可存盤,&位置)
.join()
.map(|t|((t.2.x, t. 2.y), t.0.id())
.collect::<HashMap<_, _> >()
}
編譯失敗的原因是:
error[E0599]: the method join exists for tuple (&&specs::Read<'_, EntitiesRes> ,&&specs:: Storage<'_, T, Fetch<'_, MaskedStorage<T>>, && specs::Storage<'_, Position, FetchMut<'_, MaskedStorage< Position>>)。
但是它的特質邊界沒有得到滿足 -->
src
esourcesinput_system.rs:94:14 | 94 | .join() | 。
^^^^ 方法不能在(&&specs::Read<'_, EntitiesRes> , &&specs:: Storage<'_, T, Fetch<'_, MaskedStorage<T>>, & &specs::Storage<'_, Position, FetchMut<'_, MaskedStorage< Position>>)
由于沒有滿足特征界線|=注意:以下特征
界限沒有被滿足。
&&specs::Read<'_, EntitiesRes>: specs:: Join。
這是(&&specs::Read<'_, EntitiesRes>, &&specs::Storage<'_, T, Fetch<'_, MaskedStorage<T>>, & &specs: :Storage<'_ , Position, FetchMut<'_, MaskedStorage<Position>>):specs::Join
&&specs::Storage<'_, T, Fetch<'_, MaskedStorage<T>>: specs::Join
這是(&&specs::Read<'_, EntitiesRes>, &&specs::Storage<'_, T, Fetch<'_, MaskedStorage<T>> , &&specs: :Storage<'_ , Position, FetchMut<'_, MaskedStorage<Position>>):specs::Join
&&specs::Storage<'_, Position, FetchMut<'_, MaskedStorage<Position>>>: specs::Join
這是(&&specs::Read<'_, EntitiesRes>, &&specs::Storage<'_, T, Fetch<'_, MaskedStorage< T>>, &&specs: :Storage<'_ , Position, FetchMut<'_, MaskedStorage<Position>>):specs::Join
錯誤:由于之前的錯誤而中止
。關于這個錯誤的更多資訊,請嘗試rustc --explain E0599。
error: could not compile rust-sokoban
要了解更多,請用 --verbose 再次運行該命令。
我是否真的需要引入一個特質來使其發揮作用? 如果是這樣的話,這個特性應該是什么樣子的? 我還需要做哪些其他的改變? 我是否需要增加如此多的復雜性,以至于治標不治本呢?
uj5u.com熱心網友回復:
正如我們在評論中所討論的那樣,有兩個錯誤的來源:
ReadStorage<T>或WriteStorage<T>進行操作的方法要求T是一個Component,幸運的是Movable和Immovable都已經是,所以為了解決這個問題,我們可以簡單地將T約束在這個特質中。該函式的宣告將看起來像這樣 fn collect<T: specs::Component> (...).join()方法在物件(&entities, &storable, &poss)上被呼叫,其中entities、storable、poss是已經在函式宣告中指定的參考,因此. join()被呼叫(簡單地說)在型別(&&A, &&B, &&C)上,而它被定義為(&A, &B, &C)。為了解決這個問題
我們需要在(entities, storable, positions).join()中呼叫collect函式最終版本的代碼將看起來像這樣:
fn collect<T。specs::Component>(entities: &Entities, storable: &ReadStorage<T>, positions: &WriteStorage<Position> )
-> HashMap<(u8, u8), Index> {
(物體,可存盤,位置)
.join()
.map(|t|((t.2.x, t. 2.y), t.0.id())
.collect::<HashMap<_, _> >()
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/318636.html
標籤:
上一篇:通過通用型別查找鍵的輸入
