rust - 为什么 Vec<T> 期望 &T 作为 binary_search 的参数?

标签 rust

这个问题基于这样一个假设,即 rust 中的友好/符合人体工程学的 API 应该更喜欢引用类型 Q哪里T: Borrow<Q>而不是期待 &T直接地。根据我使用其他集合类型的 API 的经验,例如 HashMap ,看来确实是这样。那说...
怎么来的binary_search方法在 Vec<T>是不是这样定义的?目前,在稳定版中,binary_search执行情况如下:

pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where
    T: Ord,
{
    self.binary_search_by(|p| p.cmp(x))
}
似乎以下将是一个更好的实现:
pub fn binary_search_modified<Q>(&self, x: &Q) -> Result<usize, usize>
where
    T: Borrow<Q>,
    Q: Ord + ?Sized,
{
    self.binary_search_by(|p| p.borrow().cmp(x))
}
上面两个API的比较:
let mut v: Vec<String> = Vec::new();
v.push("A".into());
v.push("B".into());
v.push("D".into());
let _ = v.binary_search("C"); // Compilation error!
let _ = v.binary_search(&String::from("C")); // Fine allocate and convert it to the exact type, I guess
let _ = v.binary_search_modified("C"); // Far nicer API, does the same thing
let _ = v.binary_search_modified(&String::from("C")); // Backwards compatible
作为一个更普遍的问题,决定一个方法是否应该接受的考虑因素是什么 &T&Q ... where T: Borrow<Q> ?

最佳答案

你说得对binary_search()以及其他一些方法,如 contains()可以概括为接受可以借用为 T 的任何类型,但不幸的是 Rust 1.0 发布时带有不太通用的签名。虽然看起来像使用 Borrow更严格的是,在太多情况下,尝试实现该更改会破坏类型推断。
关于这个话题有无数的 Github 问题、PR 和论坛讨论。如果您想了解修复此问题的尝试历史,我建议您从 the PR finally reverting the attempts to make binary_search() more general 开始并倒退。
关于您更一般的问题,我的建议与任何 API 设计问题相同:考虑用例。使用额外的类型参数会使代码更加复杂,并且文档和编译器错误变得不那么明显。对于 trait 上的方法,类型参数将使 trait 无法用于 trait 对象。因此,如果您可以使用 Borrow 为更通用的版本想到令人信服的用例,去吧,但在没有令人信服的用例的情况下,最好避免它。

关于rust - 为什么 Vec<T> 期望 &T 作为 binary_search 的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62988904/

相关文章:

rust - 有条件地迭代几个可能的迭代器之一

rust - 为什么这会变成堆栈溢出?

rust - panic !不会停止 Iron 服务器

rust - 如何使用 Tokio 远程关闭正在运行的任务

rust - 实现嵌套特征

dictionary - 如何编写一个函数来处理通用映射及其条目类型?

rust - 我可以将结构嵌入到 Rust 的枚举中吗?

generics - "Expected type parameter, found integer"从函数调用但不是从 main 调用

rust - 我应该为变量添加生命周期还是在 Rust 函数之间传递它

string - 从 String 中删除单个尾随换行符而不进行克隆