This question already has answers here:
Initialize a large, fixed-size array with non-Copy types
(8 answers)
Closed last month.
I want to create an array of 10 empty vectors in Rust, but [Vec::new(); 10] doesn't work as Vec doesn't implement Copy. How can I do this, and in more general terms how can I initialize a array by repeatedly calling a function?
As of Rust 1.55.0, Sep 2021
You can use array's .map() method for general functions:
let arr: [Vec<u32>; 10] = [(); 10].map(|_| Vec::with_capacity(100));
(With Rust 1.63.0, Aug 2022 consider using from_fn).
As of Rust 1.63
Use from_fn:
let array: [usize; 5] = core::array::from_fn(|i| i * 2);
assert_eq!(array, [0, 2, 4, 8, 10]);
For your specific case, you can just use Default:
let v: [Vec<String>; 10] = Default::default();
For the general case, you can create an iterator out of your function and then collect into the array using ArrayVec:
use arrayvec::ArrayVec; // 0.4.10
use std::iter;
fn make<R>(f: impl FnMut() -> R) -> [R; 10] {
let a: ArrayVec<_> = iter::repeat_with(f).collect();
a.into_inner()
.unwrap_or_else(|_| panic!("Did not have enough elements"))
}
fn main() {
let mut a = 0;
let arr = make(|| {
a += 3;
a
});
println!("{:?}", arr);
// [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
}
See also:
How do I collect into an array?
I see two possible approaches
First
A simple solution using macro
macro_rules! array {
($v: expr; 1) => ([$v]);
($v: expr; 2) => ([$v, $v]);
($v: expr; 3) => ([$v, $v, $v]);
($v: expr; 4) => ([$v, $v, $v, $v]);
($v: expr; 5) => ([$v, $v, $v, $v, $v]);
// until 32
}
let a = array![Vec::new(); 3];
It's a bit verbose, but even the standard library uses this kind of construct.
Second
After realizing a connection between this question and another that I had answered before, I wrote this solution using nodrop
extern crate nodrop;
macro_rules! array {
($e: expr; $n:expr) => (
{
use std::mem;
use std::ptr;
use nodrop::NoDrop;
struct ArrayBuilder<T> {
len: usize,
data: *mut T,
}
impl<T> Drop for ArrayBuilder<T> {
fn drop(&mut self) {
unsafe {
while self.len > 0 {
let offset = (self.len as isize) - 1;
self.len -= 1;
ptr::drop_in_place(self.data.offset(offset));
}
}
}
}
let mut v: NoDrop<[_; $n]> = NoDrop::new(unsafe {
mem::uninitialized()
});
// helps type inference for v
if false { v[0] = $e; }
let mut builder = ArrayBuilder {
len: 0,
data: (&mut *v as *mut _) as *mut _
};
unsafe {
for i in 0..$n {
ptr::write(builder.data.offset(i as isize), $e);
builder.len = i + 1;
}
}
builder.len = 0;
v.into_inner()
}
)
}
let a = array![Vec::new(); 3];
And a test that indicates that it does not leak memory
#[test]
fn test() {
static mut COUNT: usize = 0;
#[derive(Debug)]
struct X(usize);
impl Drop for X {
fn drop(&mut self) {
println!("drop {:?}", self.0);
}
}
impl X {
fn new() -> X {
unsafe {
if COUNT == 3 {
panic!();
}
let x = X(COUNT);
COUNT += 1;
x
}
}
}
array![X::new(); 6];
}
In this test, the method X::new panics when creating X(3), so X(0), X(1), X(2) must be dropped.
Others
There is an unsafe solution here.
Edit: Outdated (applies to a Rust version lower than 1.55.0):
There is a crate called arr_macro that does exactly what you want:
fn main() {
let array: [Vec<String>; 10] = arr![Vec::new(); 10];
println!("{:?}", array) // [[], [], [], [], [], [], [], [], [], []]
}
Related
Let's say I have the following array of iterators:
let arr = [0..9, 2..8, 4..8, 3..5];
How do I create an iterator that takes one element from each array every time .next() is called and returns a new array with these contents? I looked at itertools::izip and itertools::multizip, but these all didn't work with an array.
In this case, if such a function were called zip_array, I would expect the following result:
for [a, b, c, d] in zip_array(arr) {
println!("{a} {b} {c} {d}");
}
println!("end of iteration");
// 0 2 4 3
// 1 3 5 4
// end of iteration
How could one implement this function?
On nightly, this is very simple to implement (but note that the nightly implementation below may be faster):
#![feature(array_methods, array_try_map)]
pub struct ZipArray<T, const N: usize> {
array: [T; N],
}
pub fn zip_array<T: Iterator, const N: usize>(array: [T; N]) -> ZipArray<T, N> {
ZipArray { array }
}
impl<T: Iterator, const N: usize> Iterator for ZipArray<T, N> {
type Item = [T::Item; N];
fn next(&mut self) -> Option<Self::Item> {
self.array.each_mut().try_map(|i| i.next())
}
}
On stable, this require a little more work and unsafe code:
impl<T: Iterator, const N: usize> Iterator for ZipArray<T, N> {
type Item = [T::Item; N];
fn next(&mut self) -> Option<Self::Item> {
// SAFETY: It is always valid to `assume_init()` an array of `MaybeUninit`s (can be replaced
// with `MaybeUninit::uninit_array()` once stable).
let mut result: [MaybeUninit<T::Item>; N] = unsafe { MaybeUninit::uninit().assume_init() };
for (item, iterator) in std::iter::zip(&mut result, &mut self.array) {
item.write(iterator.next()?);
}
// SAFETY: We initialized the array above (can be replaced with `MaybeUninit::array_assume_init()`
// once stable).
Some(unsafe { std::mem::transmute_copy::<[MaybeUninit<T::Item>; N], [T::Item; N]>(&result) })
}
}
(Note that this does not drop items from previous iterators in case next() panics. It is not required, but a good thing to do).
On nightly you can use this code.
For stable you have to specifify the length in <[_; 4]>.
#![feature(generic_arg_infer)]
fn main() {
let mut arr = [0u8..9, 2..8, 4..8, 3..5];
for [a, b, c, d] in std::iter::from_fn(|| {
<[_;_]>::try_from(
arr.iter_mut()
.map(|x| x.next())
.collect::<Option<Vec<_>>>()?
)
.ok()
}) {
println!("{a} {b} {c} {d}");
}
println!("end of iteration");
// 0 2 4 3
// 1 3 5 4
// end of iteration
}
On stable you can use this:
pub struct ZipArray<T, const N: usize> {
array: [T; N],
}
pub fn zip_array<T: Iterator, const N: usize>(array: [T; N]) -> ZipArray<T, N> {
ZipArray { array }
}
impl<T: Iterator, const N: usize> Iterator for ZipArray<T, N>
where
<T as Iterator>::Item: Copy + Default,
{
type Item = [T::Item; N];
fn next(&mut self) -> Option<Self::Item> {
let mut item = [T::Item::default(); N];
for (index, element) in self.array.iter_mut().enumerate() {
match element.next() {
Some(value) => item[index] = value,
None => {
return None;
}
}
}
Some(item)
}
}
fn main() {
let arr = [0..9, 2..8, 4..8, 3..5];
for [a, b, c, d] in zip_array(arr) {
println!("{a} {b} {c} {d}");
}
println!("end of iteration");
}
It's probably not as performant due to copies as the unsafe version and has additional trait bounds, but it's safe.
I am in the process of writing a trait with two associated constants: the first is a usize, and the other is an array of usize where with a length equal to the first constant. Essentially, my trait is equivalent to the following:
#![feature(const_trait_impl)]
#![feature(generic_const_exprs)]
trait Foo {
const SIZE: usize;
const ARR: [usize; Self::SIZE];
}
struct S;
impl const Foo for S {
const SIZE: usize = 2;
const ARR: [usize; Self::SIZE] = [1, 2];
}
fn main() {
const TEST: &[usize; 2] = &S::ARR;
println!("{:?}", TEST);
}
As of the current nightly build, this trait definition produces the following error:
error: unconstrained generic constant
--> src\main.rs:6:5
|
6 | const ARR: [usize; Self::SIZE];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:`
Unfortunately, the suggested fix is not useful because any where bound involving Self::SIZE would be infinitely recursive. I was ready to give up until I discovered an alternative that seems to work:
#![feature(const_trait_impl)]
#![feature(generic_const_exprs)]
trait Bar {
const SIZE: usize;
fn arr() -> [usize; Self::SIZE];
}
struct S;
impl const Bar for S {
const SIZE: usize = 2;
fn arr() -> [usize; Self::SIZE] {
[1,2]
}
}
fn main() {
const TEST: &[usize; 2] = &S::arr();
println!("{:?}", TEST);
}
I am rather perplexed by this discrepancy, all things considered. Is there any way around it, or is it mostly just a matter of waiting for const language support to improve?
You can do as follows
trait Foo<const N : usize>{
const ARR : [usize; N];
}
struct S;
impl Foo<2> for S{
const ARR : [usize; 2] = [1, 2];
}
impl Foo<3> for S{
const ARR : [usize; 3] = [1, 2, 3];
}
fn main(){
const TEST : &[usize; 2] = &S::ARR;
println!("{:?}", TEST); // [1, 2]
const TEST2 : &[usize; 3] = &S::ARR;
println!("{:?}", TEST2); // [1, 2, 3]
}
How can I generate a long const array with values taken from a range?
Bonus: 1) working with no_std, 2) without using any crates
What I would like to do:
struct A {
a: i32,
b: B
}
enum B {
One,
Two
}
const AS: [A; 1024] = [A{a: 1, b: B::One}, A{a: 2, b: B::One}, ..., A{a: 1024, b: B::One}]
The furthest I got so far is:
macro_rules! generate_list {
($($a:expr)+, $variant:expr) => {
[ $( A { a: $a, b: $variant } )* ]
}
}
const AS: [A; 1024] = generate_list!(1..1025i32, B::One);
At least one problem with this seems to be that the macro is evaluated before the range expression is expanded to a list of literals.
I'm not sure if its idiomatic, but perhaps the following might work for your use case:
#[derive(Debug, Copy, Clone)]
pub struct A {
a: i32,
b: B,
}
#[derive(Debug, Copy, Clone)]
pub enum B {
One,
Two,
}
const fn gen_array<const N: usize>(offset: i32, b: B) -> [A; N] {
let mut res = [A { a: offset, b }; N];
let mut i = 0;
while i < N as i32 {
res[i as usize].a = offset + i;
i += 1;
}
res
}
const AS: [A; 42] = gen_array(0, B::One);
fn main() {
println!("{:#?}", AS);
}
Playground
I used a while loop, as a for loop is currently not allowed within a const context as E0744 indicates.
The above would generate 42 values for AS with an offset of 0:
[
A {
a: 0,
b: One,
},
A {
a: 1,
b: One,
},
...
A {
a: 41,
b: One,
},
]
The Godbolt Compiler Explorer shows that it generates the same instructions as writing it out manually.
This question already has answers here:
How do I use Serde to (de)serialize arrays greater than 32 elements, such as [u8; 128]?
(2 answers)
How do I implement a trait I don't own for a type I don't own?
(3 answers)
Closed 2 years ago.
I need to use 33-byte arrays. It looks like arrays up to and including 32 elements serialise without problems, but 33-byte arrays cause:
error[E0277]: the trait bound `[u8; 33]: _::_serde::Deserialize<'_>` is not satisfied
--> src/main.rs:54:2
|
54 | foo: [u8; 33]
| ^^^ the trait `_::_serde::Deserialize<'_>` is not implemented for `[u8; 33]`
|
= help: the following implementations were found:
<&'a [u8] as _::_serde::Deserialize<'de>>
<[T; 0] as _::_serde::Deserialize<'de>>
<[T; 10] as _::_serde::Deserialize<'de>>
<[T; 11] as _::_serde::Deserialize<'de>>
and 30 others
= note: required by `_::_serde::de::MapAccess::next_value`
They evidently decided that 32 was a good place to stop. How can I add support for 33 element arrays?
You can't implement a trait you don't own for a type you don't own, but unfortunately, in this particular case, you don't have to.
For serialization, support of big arrays is pretty easy
struct S {
#[serde(serialize_with = "<[_]>::serialize")]
arr: [u8; 256],
}
Source
This coerces the array to a slice and serializes that instead.
For de-serialization, it is a bit more complicated.
serde's own author recommends the following
#[macro_use] extern crate serde_derive;
extern crate serde; extern crate serde_json;
use std::fmt; use std::marker::PhantomData;
use serde::ser::{Serialize, Serializer, SerializeTuple};
use serde::de::{Deserialize, Deserializer, Visitor, SeqAccess, Error};
trait BigArray<'de>: Sized {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer;
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>;
}
macro_rules! big_array {
($($len:expr,)+) => {
$(
impl<'de, T> BigArray<'de> for [T; $len]
where T: Default + Copy + Serialize + Deserialize<'de>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut seq = serializer.serialize_tuple(self.len())?;
for elem in &self[..] {
seq.serialize_element(elem)?;
}
seq.end()
}
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error>
where D: Deserializer<'de>
{
struct ArrayVisitor<T> {
element: PhantomData<T>,
}
impl<'de, T> Visitor<'de> for ArrayVisitor<T>
where T: Default + Copy + Deserialize<'de>
{
type Value = [T; $len];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("an array of length ", $len))
}
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error>
where A: SeqAccess<'de>
{
let mut arr = [T::default(); $len];
for i in 0..$len {
arr[i] = seq.next_element()?
.ok_or_else(|| Error::invalid_length(i, &self))?;
}
Ok(arr)
}
}
let visitor = ArrayVisitor { element: PhantomData };
deserializer.deserialize_tuple($len, visitor)
}
}
)+
}
}
big_array! {
40, 48, 50, 56, 64, 72, 96, 100, 128, 160, 192, 200, 224, 256, 384, 512,
768, 1024, 2048, 4096, 8192, 16384, 32768, 65536, }
#[derive(Serialize, Deserialize)]
struct S {
#[serde(with = "BigArray")]
arr: [u8; 64], }
fn main() {
let s = S { arr: [1; 64] };
let j = serde_json::to_string(&s).unwrap();
println!("{}", j);
serde_json::from_str::<S>(&j).unwrap(); }
Source
This has been published in the serde-big-array crate.
I'm having trouble initializing a fixed length array. My attempts so far all result in the same "use of possibly uninitialized variable: foo_array" error:
#[derive(Debug)]
struct Foo { a: u32, b: u32 }
impl Default for Foo {
fn default() -> Foo { Foo{a:1, b:2} }
}
pub fn main() {
let mut foo_array: [Foo; 10];
// Do something here to in-place initialize foo_array?
for f in foo_array.iter() {
println!("{:?}", f);
}
}
error[E0381]: use of possibly uninitialized variable: `foo_array`
--> src/main.rs:13:14
|
13 | for f in foo_array.iter() {
| ^^^^^^^^^ use of possibly uninitialized `foo_array`
I implemented the Default trait, but Rust does not seem to call this by default akin to a C++ constructor.
What is the proper way to initialize a fixed length array? I'd like to do an efficient in-place initialization rather than some sort of copy.
Related: Why is the Copy trait needed for default (struct valued) array initialization?
Related: Is there a way to not have to initialize arrays twice?
The safe but somewhat inefficient solution:
#[derive(Copy, Clone, Debug)]
struct Foo {
a: u32,
b: u32,
}
fn main() {
let mut foo_array = [Foo { a: 10, b: 10 }; 10];
}
Since you're specifically asking for a solution without copies:
use std::mem::MaybeUninit;
#[derive(Debug)]
struct Foo {
a: u32,
b: u32,
}
// We're just implementing Drop to prove there are no unnecessary copies.
impl Drop for Foo {
fn drop(&mut self) {
println!("Destructor running for a Foo");
}
}
pub fn main() {
let array = {
// Create an array of uninitialized values.
let mut array: [MaybeUninit<Foo>; 10] = unsafe { MaybeUninit::uninit().assume_init() };
for (i, element) in array.iter_mut().enumerate() {
let foo = Foo { a: i as u32, b: 0 };
*element = MaybeUninit::new(foo);
}
unsafe { std::mem::transmute::<_, [Foo; 10]>(array) }
};
for element in array.iter() {
println!("{:?}", element);
}
}
This is recommended by the documentation of MaybeUninit.
You can use the arrayvec crate:
Cargo.toml
[package]
name = "initialize_array"
version = "0.1.0"
edition = "2018"
[dependencies]
arrayvec = "0.7.2"
src/main.rs
use arrayvec::ArrayVec;
use std::iter;
#[derive(Clone)]
struct Foo {
a: u32,
b: u32,
}
fn main() {
let foo_array: [Foo; 10] = iter::repeat(Foo { a: 10, b: 10 })
.take(10)
.collect::<ArrayVec<_, 10>>()
.into_inner()
.unwrap_or_else(|_| unreachable!());
}
The easiest way is to derive Copy on your type and initialize the array with that, copying the element N times:
#[derive(Copy)]
struct Foo {
a: u32,
b: u32,
}
let mut foo_array = [Foo { a: 1, b: 2 }; 10];
If you want to avoid copying, there are a couple options. You can use the Default trait:
let mut foo_array: [Foo; 10] = Default::default();
However, this is limited to arrays up to 32 elements. With const generics, it is now possible for the standard library to provide Default for all arrays. However, this would be a backward incompatible change for subtle reasons that are being worked on.
For now, you can take advantage of the fact that const values are also allowed in array repetition expressions:
const FOO: Foo = Foo { a: 1, b: 2 };
let mut foo_array = [FOO; 10];
If you're on nightly, you can use array::map:
#![feature(array_map)]
let mut foo_array = [(); 10].map(|_| Foo::default())