Macro with variable arguments of different types

I'm trying to create macros to make it easier to create small instances of a custom tree type. To do this, I would like to specify the child objects as either nodes or integers (without explicitly converting them to type Node). My attempt below is that it does not work, since the type is $xresolved as MDTree, with the message expected enum MDTree, found integral variable.

pub struct MultiNode {
    children: Vec<MDTree>
}
impl MultiNode {
    pub fn new(children: Vec<MDTree>) -> Box<MultiNode> {
        return Box::new(MultiNode { children: children });
    }
}
pub enum MDTree {
    Single(u32),
    Prime(Box<MultiNode>),
    Degenerate(Box<MultiNode>),
}
macro_rules! mod_single {
    ($x:expr) => { MDTree::Single($x) }
}
macro_rules! mod_multi {
    ($($x:expr),*) => {{
        let mut children: Vec<MDTree> = Vec::new();
        $(
            match $x {
                0...4294967295 => { children.push(mod_single!($x)); }
                _ => { children.push($x); }
            }
        )*
        MultiNode::new(children)
    }}
}
macro_rules! mod_prime {
    ($($x:expr),*) => { MDTree::Prime(mod_multi!($($x),*)) }
}
macro_rules! mod_degen {
    ($($x:expr),*) => { MDTree::Degenerate(mod_multi!($($x),*)) }
}
fn main() {
    let md: MDTree = mod_prime!(0, mod_degen!(1,2));
}

Is there a way to fix this without recording mod_prime!(mod_single(0), mod_degen!(mod_single(1),mod_single(2)))or similar?

+4
source share
2 answers

A macro cannot talk about the type of its operands, since macro decomposition occurs before type resolution.

, ! , , . ? , ! From Into , , .

, mod_multi! :

macro_rules! mod_multi {
    ($($x:expr),*) => {{
        let mut children: Vec<MDTree> = Vec::new();
        $(
            children.push($x.into());
        )*
        MultiNode::new(children)
    }}
}

, $x; , into() . , , , .

Into , u32, MDTree. Into , From, From Into. impl<T> From<T> for T, MDTree. u32. :

impl From<u32> for MDTree {
    fn from(value: u32) -> MDTree {
        mod_single!(value)
    }
}

- !

+7

, , , , ( ):

#[derive(Debug)]
pub enum MDTree {
    Single(u32),
    Prime(Vec<MDTree>),
    Degenerate(Vec<MDTree>),
}

macro_rules! mdtree {
    ([$($sub:tt),*]) => {{
        MDTree::Prime(vec!($(mdtree!($sub),)*))
    }};
    ({$($sub:tt),*}) => {{
        MDTree::Degenerate(vec!($(mdtree!($sub),)*))
    }};
    ($e:expr) => {
        MDTree::Single($e)
    };
}

fn main() {
    println!("{:?}", mdtree!([1, [2, 3], {4, 5}]));
}

(, { [ , , , , .

+6

Source: https://habr.com/ru/post/1663482/


All Articles