Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a generic type parameterized by a number [duplicate]

Tags:

generics

rust

I'm writing an NGram library in Rust. I want to create a 'generic' ngram where the size doesn't need to be determined until compilation time (as opposed to when I code it). A little code might help make that clear.

Here is basically what I want to be able to do:

pub type Ngram<N> = Vec<[String; N]>;

and then to use it, you simply do something like this:

let vec = Ngram::<5>::new();

And you would have created a five-gram (or more precisely, a Vec<[String; 5]>). Is something like that possible. I really don't want to do something like this:

 pub type Ngram<N> = Vec<N>;
 ...
 let vec = Ngram::<[String; 5]>::new();

That would mostly defeat the purpose of creating the type.

like image 962
wmaxlees Avatar asked Jul 07 '15 19:07

wmaxlees


People also ask

How do you provide a generic parameterized type?

In order to use a generic type we must provide one type argument per type parameter that was declared for the generic type. The type argument list is a comma separated list that is delimited by angle brackets and follows the type name. The result is a so-called parameterized type.

Can a generic class have multiple parameters?

A Generic class can have muliple type parameters.

Can you create instances of generic type parameters?

A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the MakeGenericType method.


2 Answers

This isn't possible in Rust 1.0. The size of an array can't be generic.

like image 131
A.B. Avatar answered Sep 24 '22 14:09

A.B.


It will be possible in the future, but until then, the best way to do it is:

Use a base trait for a fixed size array, implement it with macros for all the sizes you need. With the trait, you don't need more macros for the rest of the functionality.

In normal use I bet that you don't have to type let vec = Ngram::<[String; 5]>::new();, you can just say:

let vec = Ngram::<[_; 5]>::new();

which is slightly better. If you use your supporting trait to constrain the array's element type to String, then this writing is never ambiguous.

See the crate arrayvec's code for more info.

like image 41
bluss Avatar answered Sep 25 '22 14:09

bluss