How can I initialize an array using a function? [duplicate] - arrays

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

How to turn an array of iterators into an iterator of arrays?

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.

How to avoid "unconstrained generic constant" with dependent associated constants in traits?

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]
}

Const array from range

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.

How can I implement serde::Deserialize for arrays larger than 32? [duplicate]

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.

How to initialize an array with an iterator in Rust? [duplicate]

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())

Resources