在嘗試撰寫接收異步閉包的函式時,我發現它有點棘手。
我知道正確的版本是
pub async fn f1<F, Fut>(f: F) -> u32
where
F: Fn(u32) -> Fut,
Fut: Future<Output = u32>,
{
f(9u32).await
}
但是,whereRust 檔案中的子句說這只是表達這些型別的一種便捷方式,因此我嘗試洗掉 where 子句,如下所示:
pub async fn f2(f: Fn(u32) -> Future<Output = u32>) -> u32 {
f(9u32).await
}
令我驚訝的是,Rust 拒絕編譯它,說
error: trait objects must include the dyn keyword
任何人都知道洗掉where條款的正確方法是什么?
where條款在這里發揮了什么魔力?
uj5u.com熱心網友回復:
在你的第一個片段中,你必須限制:
F必須執行Fn(u32) -> Fut。Fut必須執行Future<Output = u32>。
但是在您的第二個代碼段中沒有任何限制。行內約束的語法是使用impl關鍵字:
pub async fn f2(f: impl Fn(u32) -> Future<Output = u32>) -> u32 {
f(9u32).await
}
這也不起作用,因為impl僅適用于Fn特征,而不適用于回傳特征,因此編譯器抱怨不允許使用裸特征,您應該將dyn其添加到其中。
不好的建議,因為:
pub async fn f2(f: impl Fn(u32) -> dyn Future<Output = u32>) -> u32 {
f(9u32).await
}
也不會起作用,因為dyn Trait型別未確定大小且無法回傳。
您可以impl在那里嘗試另一個,它通常適用于回傳型別,但是:
pub async fn f2(f: impl Fn(u32) -> impl Future<Output = u32>) -> u32 {
f(9u32).await
}
在函式和方法回傳型別之外不允許 impl Trait`
我所知道的限制Fn特征回傳型別的唯一語法是使用以下where語法:
pub async fn f2<Fut>(f: impl Fn(u32) -> Fut) -> u32
where
Fut: Future<Output = u32>,
{
f(9u32).await
}
但是現在您處于完整where模式,我認為沒有理由保留行內約束。我個人認為在同一個函式上有兩種語法是不好的風格。
uj5u.com熱心網友回復:
假設您通過示例參考Rust:
那里的示例不使用特征物件(例如foo: Box<dyn SomeTrait>)或存在型別(例如foo: impl SomeTrait),但在宣告站點為泛型型別添加了邊界:
impl <A: TraitB TraitC, D: TraitE TraitF> MyTrait<A, D> for YourType {}
// Expressing bounds with a `where` clause
impl <A, D> MyTrait<A, D> for YourType where
A: TraitB TraitC,
D: TraitE TraitF {}
在你的情況下,你會寫:
pub async fn f2<F: Fn(u32) -> Fut, Fut: std::future::Future<Output = u32>>(f: F) -> u32 {
f(9u32).await
}
而不是將Fn(u32) -> Future<Output = u32>邊界作為 的型別f。請注意,您還需要為Fut: Future<Output = u32>閉包回傳的未來宣告一個泛型型別,否則您將再次回傳原始特征物件。
正如@rodrigo 所提到的,也可以使用該impl SomeTrait符號從函式中完全洗掉泛型型別引數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/403384.html
標籤:
下一篇:更新變數的Python異步呼叫
