问题描述
在 Rust 中,向量使用 usize
进行索引,因此在编写时
In Rust, vectors are indexed using usize
, so when writing
let my_vec: Vec<String> = vec!["Hello", "world"];
let index: u32 = 0;
println!("{}", my_vec[index]);
你得到一个错误,因为索引应该是 usize
类型.我知道这可以通过将 index 显式转换为 usize
来解决:
you get an error, as index is expected to be of type usize
. I'm aware that this can be fixed by explicitly converting index to usize
:
my_vec[index as usize]
但这写起来很乏味.理想情况下,我只是通过实现
but this is tedious to write. Ideally I'd simply overload the []
operator by implementing
impl<T> std::ops::Index<u32> for Vec<T> { ... }
但这是不可能的,因为 Rust 禁止这样做(因为 trait 和 struct 都不是本地的).我能看到的唯一替代方法是为 Vec
创建一个包装器类,但这意味着还必须编写大量函数包装器.有没有更优雅的方法来解决这个问题?
but that's impossible as Rust prohibits this (as neither the trait nor struct are local). The only alternative that I can see is to create a wrapper class for Vec
, but that would mean having to write lots of function wrappers as well. Is there any more elegant way to address this?
推荐答案
如果没有明确的用例,很难推荐最佳方法.
Without a clear use case it is difficult to recommend the best approach.
这里基本上有两个问题:
There are basically two questions here:
- 您真的需要索引吗?
- 你真的需要使用
u32
作为索引吗?
- do you really need indexing?
- do you really need to use
u32
for indices?
当使用函数式编程风格时,通常不需要索引,因为您对迭代器进行操作.在这种情况下,Vec
只为 usize
实现 Index
的事实并不重要.
When using functional programming style, indexing is generally unnecessary as you operate on iterators instead. In this case, the fact that Vec
only implements Index
for usize
really does not matter.
如果你的算法真的需要索引,那么为什么不使用usize
?从 u32
转换为 usize
的方法有很多种,在最后一刻转换是一种可能,但是还有其他网站可以进行转换,如果您找到一个阻塞点(或创建它),您只需进行少量转换即可逃脱.
If your algorithm really needs indexing, then why not use usize
? There are many ways to convert from u32
to usize
, converting at the last moment possible is one possibility, but there are other sites where you could do the conversion, and if you find a chokepoint (or create it) you can get away with only a handful of conversions.
至少,这是 YAGNI 的观点.
At least, that's the YAGNI point of view.
就我个人而言,作为一个类型怪胎,我倾向于把很多东西都包装起来.我只是喜欢添加语义信息,因为让我们面对它Vec
只是没有任何意义.
Personally, as a type freak, I tend to wrap things around a lot. I just like to add semantic information, because let's face it Vec<i32>
just doesn't mean anything.
Rust 提供了一种创建包装结构的简单方法:struct MyType(WrappedType);
.就是这样.
Rust offers a simple way to create wrapper structures: struct MyType(WrappedType);
. That's it.
一旦你有了自己的类型,添加索引就很容易了.有几种方法可以添加其他操作:
Once you have your own type, adding indexing is easy. There are several ways to add other operations:
- 如果只有少数操作有意义,那么最好显式添加.
- 如果需要很多操作,并且你不介意暴露下面是一个
Vec
的事实,那么你可以暴露它:- 通过公开:
struct MyType(pub WrappedType);
,用户可以调用.0
来访问它. - 通过实现
AsRef
和AsMut
,或创建一个 getter. - 通过实现
Deref
和DerefMut
(这是隐式的,确保你真的想要).
- if only a few operations make sense, then adding explicitly is best.
- if many operations are necessary, and you do not mind exposing the fact that underneath is a
Vec<X>
, then you can expose it:- by making it public:
struct MyType(pub WrappedType);
, users can then call.0
to access it. - by implementing
AsRef
andAsMut
, or creating a getter. - by implementing
Deref
andDerefMut
(which is implicit, make sure you really want to).
当然,打破封装以后可能会很烦人,因为它也阻止了不变量的维护,所以我认为这是最后的解决方案.
Of course, breaking encapsulation can be annoying later, as it also prevents the maintenance of invariants, so I would consider it a last ditch solution.
这篇关于按 32 位整数索引向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- by making it public:
- 通过公开: