“我的第一次生锈”:枚举 `Option<&mut ...>` 存在方法 `unwrap_or_default`,但不满足其特征界限
Posted
技术标签:
【中文标题】“我的第一次生锈”:枚举 `Option<&mut ...>` 存在方法 `unwrap_or_default`,但不满足其特征界限【英文标题】:"my first rust": the method `unwrap_or_default` exists for enum `Option<&mut ...>`, but its trait bounds were not satisfied 【发布时间】:2021-07-13 20:50:27 【问题描述】:我的第一个rust
程序/函数应该遍历目录树并提供HashMap
与K(mime_as_string)
和V(count_sum, size_sum)
。我想要它的 FP 风格。
所以我拥有的是这样的:
fn files_info4(rootpath: &str)
struct FTypeStats
count: u64,
size: u64,
impl Default for FTypeStats
fn default() -> Self
FTypeStats
count: 0,
size: 0,
// get file type stats directly/functionally/lazy
let fts = WalkDir::new(rootpath)
.min_depth(1)
.max_depth(99)
.into_iter()
.filter_map(|entry| entry.ok())
.map(|entry| (entry, entry.metadata().map_or(false, |m| m.is_file())))
.filter(|(e, f)| *f)
.fold(HashMap::new(), | mut acc: HashMap<String, FTypeStats>, (e, _) |
let ftype = tree_magic::from_filepath(e.path());
acc.get_mut(&ftype).unwrap_or_default().count += 1;
acc.get_mut(&ftype).unwrap_or_default().size += e.metadata().map_or(0, |m| m.len());
acc
);
遇到错误后我在哪里做impl Default
:
error[E0599]: the method `unwrap_or_default` exists for enum `Option<&mut FTypeStats>`, but its trait bounds were not satisfied
--> src/main.rs:54:29
|
54 | acc.get_mut(&ftype).unwrap_or_default().count += 1;
| ^^^^^^^^^^^^^^^^^ method cannot be called on `Option<&mut FTypeStats>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`&mut FTypeStats: Default`
但它仍然没有帮助,即仍然存在相同的错误。
问题:
-
如何编译/运行
可以优化评估链吗? (
fold
中的代码实际上是否正确,例如我需要为 FTypeStats
进行的分配和初始化默认/初始值?(感觉有点“隐含”))
TIA!
【问题讨论】:
【参考方案1】:这里有多个问题:首先,在HashMap
上调用.get_mut()
会给您一个Option
,即None
,以防密钥不在地图中。 Option
本身与地图分离(除了生命周期约束),因此在None
-case 中,没有链接返回到地图中,可以将默认构造的值放在适当的位置。
其次,正如错误消息所说,方法unwrap_or_default()
需要Option
的内部类型才能实际实现Default
,在本例中为&mut FTypeStats
。这样的实现不仅在您的代码中不存在,而且这样做也非常困难,因为凭空生成对某种类型的(有效)可变引用 - 这是Default
的重点 - 实际上是不可能的。
解决方案是在HashMap
上使用entry()
API 而不是get_mut()
:
*acc.entry(&ftype).or_default().count += 1;
对entry()
的调用为您提供了一个代理值,指向&ftype
位于或将位于HashMap
中的任何位置。对or_default()
的调用总是会给你一个&mut FTypeStats
。如果&ftype
不在映射中,它使用Default
on FTypeStats
(不是Default
on &mut FTypeStats
)生成一个新条目,插入它,并为您提供一个可变引用。
【讨论】:
谢谢,这让我更接近了,虽然我现在遇到了一个新问题:如果我的哈希键是一个值 (String
) 我得到 使用移动值:ftype
我第二次索引(对于+size
);如果我尝试通过使用引用(例如&str
)作为键来解决这个问题,我会得到(对于两个索引)ftype
的寿命不够长。如果我尝试通过为FTypeStats
实现add
并像这样添加acc.entry(ftype).or_default().add(FTypeStatscount: 1, size: e.metadata().map_or(0, |m| m.len()));
来解决那个(天真?),它会运行但所有值都是0
。 (而且比我的go
版本慢很多)以上是关于“我的第一次生锈”:枚举 `Option<&mut ...>` 存在方法 `unwrap_or_default`,但不满足其特征界限的主要内容,如果未能解决你的问题,请参考以下文章