generics - 为什么在 Rust 中使用泛型类型引用时必须指定生命周期?
问题描述
我正在实现 Rust 的TryFrom
trait 作为serde_json::value::Value
参考,以及一个将 a 转换Vec<Value>
为 a的函数Vec<T>
,其中T
实现了TryFrom<&Value>
。因为我必须在我的函数中为引用指定生命周期,所以Value
我无法返回T::try_from
(借用值被丢弃)的结果。
我尝试了另一种可行的方法;创建我自己的特征,类似于TryFrom
但没有泛型。这行得通,但我不明白为什么我不能使用TryFrom
和泛型,因为特征已经存在。
我的通用代码引发编译时错误:
impl TryFrom<&Value> for Channel {
type Error = &'static str;
fn try_from(value: &Value) -> Result<Self, Self::Error> {
let title = value.get("title").ok_or("couldn't find title property in json")?
.as_str().ok_or("title was not a string")?;
let name = value.get("user_name").ok_or("couldn't find user_name property in json")?
.as_str().ok_or("user_name was not a string")?;
Ok(Channel {
title: String::from(title),
user_name: String::from(name)
})
}
}
// I must add a lifetime below. Please ignore the self reference.
fn get_many_generic<'a, T: TryFrom<&'a Value>>(&self, url_str: &str) -> Result<Vec<T>, Box<dyn std::error::Error>> {
// perform_get returns a serde_json::Value
let mut value = &self.perform_get(url_str)?;
if let Value::Object(map) = value {
value = map.get("data").ok_or("found a map without a 'data' property when expecting an array")?;
}
if let Value::Array(vec) = value {
Ok(vec.iter()
.filter_map(|item|
match T::try_from(item) {
Ok(model) => Some(model),
Err(e) => {
println!("Could not deserialize value {}", item);
None
}
}
).collect())
}
else {
Err(Box::new(
Error::new(format!("Expected array from {}, but didn't receive one.", url_str))
))
}
}
我的代码有效:
pub trait TryFromValue where Self: std::marker::Sized {
fn try_from_value(value: &Value) -> Result<Self, Box<dyn Error>>;
}
impl TryFromValue for Channel {
fn try_from_value(value: &Value) -> Result<Channel, Box<dyn Error>> {
let title = value.get("title").ok_or("couldn't find title property in json")?
.as_str().ok_or("title was not a string")?;
let name = value.get("user_name").ok_or("couldn't find user_name property in json")?
.as_str().ok_or("user_name was not a string")?;
Ok(Channel {
title: String::from(title),
user_name: String::from(name)
})
}
}
fn get_many<T: TryFromValue>(&self, url_str: &str) -> Result<Vec<T>, Box<dyn std::error::Error>> {
// perform_get returns a serde_json::Value
let mut value = &self.perform_get(url_str)?;
if let Value::Object(map) = value {
value = map.get("data").ok_or("found a map without a 'data' property when expecting an array")?;
}
if let Value::Array(vec) = value {
Ok(vec.iter()
.filter_map(|item|
match T::try_from_value(item) {
Ok(model) => Some(model),
Err(e) => {
println!("Could not deserialize value {}. Error {}", item, e);
None
}
}
).collect())
}
else {
Err(Box::new(
Error::new(format!("Expected array from {}, but didn't receive one.", url_str))
))
}
}
为什么这种方法有效,但第一个代码示例失败了?
解决方案
更高等级的特征界限(由 trentcl 建议)解决了这个问题。查看他们的评论。
推荐阅读
- javascript - 试图打开特定选项卡的弹出窗口
- angular - Ionic ,使用 ion-select 并尝试将值从子级传递给父级不起作用
- deep-learning - 使用面部标志作为输入的好方法
- python-3.x - 如何使用 django 3 在模型管理员的更改列表视图页面中上传文件来解决“app_list”的 NoReverseMatch 异常?
- javascript - OneNote 2016 加载项选项
- grep - grep 命令的输出不会写入文件
- latex - 在同一行中有两个项目索引
- c# - DataGrid 通用样式未应用于整个 DataGrid
- microsoft-graph-api - 我可以使用 Microsoft Graph API 获取共享点文档库中的文件夹 ID 吗?
- c# - WPF Binding - 从 ComboBox 获取图像的路径