Rust:是否有类似于C99指定范围初始化器的数组功能?

huangapple go评论65阅读模式
英文:

Rust: is there something like C99 designated range initializer for arrays?

问题

类似的问题在在Rust中是否有获取C99数组指定符或替代方案的方法?中提出过,但那里的答案不能为给定的范围初始化一个值。

例如,

int a[10] = { [4 ... 8] = 10 };

Rust中的常量数组如何在范围上使用初始化程序?如果我们不使用const,可以通过fill()方法完成:

let mut a: [i32; 10] = [0; 10];
a[4..9].fill(10);

fill()无法在const块中使用。

英文:

The similar question is asked in Is there a way to get C99 array designators or alternative in Rust?, but the answers there cannot initialize a value for a give range.

For example,

int a[10] = { [4 ... 8] = 10 };

How do const arrays in Rust use an initializer on the range? If we don't use const, it can be done by fill() method:

let mut a: [i32; 10] = [0; 10];
a[4..9].fill(10);

But fill() cannot be used in const block.

答案1

得分: 4

没有内置的方法来完成这个,但可以使用宏自己创建它:

macro_rules! array_ranged_init {
    ( $default_value:expr $(, $($min:literal)? .. $($max:literal)? = $value:expr)* ; $len:expr ) => {
        {
            let mut array = [$default_value; $len];
            $(
                #[allow(unused_variables)]
                let min = 0;
                $(let min = $min;)?
                
                #[allow(unused_variables)]
                let max = $len;
                $(let max = $max;)?
                
                let mut i = min;
                while i < max {
                    array[i] = $value;
                    i += 1;
                }
            )*
            array
        }
    }
}

然后你可以像这样使用这个宏:

static DATA: [i32; 10] = array_ranged_init![0, 4..9 = 10; 10];

#[test]
fn test() {
    assert_eq!(DATA, [0, 0, 0, 0, 10, 10, 10, 10, 10, 0])
}

这个宏允许你包含多个范围:

static DATA: [i32; 12] = array_ranged_init![
    0,
    1..6 = 4,
    10.. = 6,
    ..1 = 1;
    12
];

#[test]
fn test() {
    assert_eq!(DATA, [1, 4, 4, 4, 4, 4, 0, 0, 0, 0, 6, 6])
}
英文:

There is no built-in way to do this, but it's possible to create it yourself with a macro:

macro_rules! array_ranged_init {
    ( $default_value:expr $(, $($min:literal)? .. $($max:literal)? = $value:expr)* ; $len:expr ) =&gt; {
        {
            let mut array = [$default_value; $len];
            $(
                #[allow(unused_variables)]
                let min = 0;
                $(let min = $min;)?
                
                #[allow(unused_variables)]
                let max = $len;
                $(let max = $max;)?
                
                let mut i = min;
                while i &lt; max {
                    array[i] = $value;
                    i += 1;
                }
            )*
            array
        }
    }
}

You can then use the macro like this:

static DATA: [i32; 10] = array_ranged_init![0, 4..9 = 10; 10];

#[test]
fn test() {
    assert_eq!(DATA, [0, 0, 0, 0, 10, 10, 10, 10, 10, 0])
}

This macro allows you to include multiple ranges:

static DATA: [i32; 12] = array_ranged_init![
    0,
    1..6 = 4,
    10.. = 6,
    ..1 = 1;
    12
];

#[test]
fn test() {
    assert_eq!(DATA, [1, 4, 4, 4, 4, 4, 0, 0, 0, 0, 6, 6])
}

huangapple
  • 本文由 发表于 2023年6月12日 23:21:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76458084.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定