Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I iterate arguments of a macros in Rust?

Tags:

rust

I am trying to create a macro that fills first elements of a vector with a fixed size. The rest of elements should be zero. I wrote:

const SIZE: usize = 3;

#[derive(Debug)]
struct MyVec {
    data: [f32; SIZE]
}

macro_rules! my_vec {
    ($($x:expr),*) => [{
        let mut data: [f32; SIZE] = [0.0; SIZE];
        for (i, e) in x.enumerate() {
            data[i] = e;
        }
        MyVec { data }
    }]
}

fn main() {
    let v = my_vec![1.0, 2.0];
    println!("{:?}", v);  // must be MyVec { data: [1.0, 2.0, 0.0] }
}

It looks like I try to iterate the arguments in a wrong way. How can I fix it?

like image 909
Fomalhaut Avatar asked Dec 24 '19 12:12

Fomalhaut


People also ask

Can a macro return a value Rust?

No, macros operate on syntax only. If there is a matcher that is ($arg:expr, &str) , the latter half of that expects a literal &str to be provided — it does not indicate that $arg is a string.

Can you use macros in Rust?

The most widely used form of macros in Rust is the declarative macro. These are also sometimes referred to as “macros by example,” “ macro_rules! macros,” or just plain “macros.” At their core, declarative macros allow you to write something similar to a Rust match expression.

Is macro_rules a macro?

macro_rules allows users to define syntax extension in a declarative way. We call such extensions "macros by example" or simply "macros". Each macro by example has a name, and one or more rules.

How do I export macros in Rust?

macros can be exported from the current crate using #[macro_export] . Note that this ignores all visibility. Given the following definition for a library package macs : mod macros { #[macro_export] macro_rules!


1 Answers

You could do this,

const SIZE: usize = 3;

#[derive(Debug)]
struct MyVec {
    data: [f32; SIZE],
}

macro_rules! my_vec {
    ( $( $x:expr ),* ) => {
        {
            let mut data: [f32; SIZE] = [0.0; SIZE];
            let mut index = 0;
            $(
                #[allow(unused_assignments)]
                {
                    data[index] = $x;
                    index = index + 1;
                }
            )*
            MyVec { data }
        }
    };
}

fn main() {
    let v = my_vec![1.0, 2.0];
    println!("{:?}", v); // print MyVec { data: [1.0, 2.0, 0.0] }
}

The code inside the $(...)* will be expanded for each matches.

like image 60
Abdul Niyas P M Avatar answered Sep 27 '22 00:09

Abdul Niyas P M