Is there any traits in std representing mut indexable array that can query its length?


#1

I know there is an IndexMut which defines the [] operator, but I didn’t find any trait representing a struct we can query the number of elements in it. For example in Vec, there is a method ``length’’, but it is defined only for struct Vec, not any traits.

What if I want to constrain some generic parameter T to require it has a method called .length() or .size()?

Of course I can write my own HasLength trait, but I wonder if there is any official solution.

Thanks.


#2

There is not. At least, there isn’t anything quite like what you’re looking for.

Seeing how long the rust community has survived without such a trait, it’s worth asking what you’re trying to use it for. Unless you require random access, chances are your needs may be better served by the Iterator API.


#3

Are you asking for some generic Length trait which all collections should implement? I’m not sure there’s any benefit of having it as a trait instead of the individual methods on each container. For one, if it were a trait you’d need to import it just to use the length() method.

The main reason you want to use a trait is for polymorphism so you can be generic over anything implementing that interface. Of itself, knowing the length of something without access to methods for also mutating a collection isn’t terribly useful, so there would be no need to make it a trait.

e.g.

pub trait Length {
  fn length(&self) -> usize;
  fn is_empty(&self) -> bool { self.length() == 0 }
}

#4

What I actually want to do is to write some numerical computing function, that can treat anything looks like''a vector to be a vector. I don't want to pass iterator to the function. The minimum requirement of how something canlooks like’’ a vector, in my opinion, it can be accessed through [] and its length can be queried.


#5

Well, there is stable std::iter::ExactSizeIterator that allows to know length of an iterator. There is also unstable std::iter::RandomAccessIterator, and its description says that ExactSizeIterator + Index should be used instead.

That being said, I find it hard to write a generic function that uses ExactSizeIterator and Index together. This is my best try, and it still doesn’t compile. Maybe someone can fix it. Iterators themselves are not Index, so the idea is to make an iterator out of &mut Vec<T>, get the length and destroy the iterator, and then use Index.

There is also len-trait crate that does what you ask.


#6

I’d love to design such a trait, just haven’t sat down to do it. My goal would be to encompass various linear random-accessible collections regardless if they are contiguous or not. I’m thinking it needs to be a number of traits to cover the various aspects.

For instance, it would be neat if algorithms written in terms of such a trait could just as easily be applied to a reversed view of a slice as its normal “forward” view.


#7

Rust’s solution to this is to just use non-generic slices. Vec and arrays can be converted to a slice. You can use T: AsMut<[T]>> if you want to spare caller from writing &mut.


#8

Slices work well for this when you can return a slice from your datastructure. This breaks down when storage isn’t contiguous though.


#9

Isn’t there a .len() function you can call on arrays, or am I not understanding the question?


#10

Perhaps you could give more details about your domain here?

It’s fairly typical for such things to make their own Vector3<T> types, for example, so they can do things like override + and (scalar) * following the vector space definitions, as libraries cannot overload operators for std types like Vec or VecDeque.