Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 在[expr*]、path[tt*]和ident[tt*]分支之后匹配单个expr的宏_Macros_Rust - Fatal编程技术网

Macros 在[expr*]、path[tt*]和ident[tt*]分支之后匹配单个expr的宏

Macros 在[expr*]、path[tt*]和ident[tt*]分支之后匹配单个expr的宏,macros,rust,Macros,Rust,我正在尝试制作一个宏,我可以用以下方式调用它: mactest!(some::Path[1, 2, AnotherName[3, 4]]) 这相当于以下内容: make_result( "some::Path", 1.convert(), 2.convert(), make_result( "AnotherName", 3.convert(), 4.convert() ) ) 其中,conver

我正在尝试制作一个宏,我可以用以下方式调用它:

mactest!(some::Path[1, 2, AnotherName[3, 4]])
这相当于以下内容:

make_result(
    "some::Path", 
    1.convert(), 
    2.convert(), 
    make_result(
        "AnotherName", 
        3.convert(), 
        4.convert()
    )
)
其中,
convert
是将为一组类型实现的特性。(
convert
make_result
具有相同的结果类型)

就我所知:

// Note: u32 is used as an example result type. 
// The real code attempts to create a more complicated object.

trait Foo {
    fn convert(&self) -> u32;
}

fn make_result(name: &str, data: Vec<u32>) -> u32 {
    // This example ignores name and makes a meaningless result
    data.iter().fold(0,|a, &b| a + b)
}


#[macro_export]
macro_rules! mactest {
    ( [ $($inner:expr),* ] ) => {{
        let mut result = Vec::new();
        $(
            // Process each element.
            result.push(mactest!($inner));
        )*
        result
    }};
    ($name:path [ $($inner:tt),* ] ) => {
        make_result(stringify!($name), mactest!([$($inner),*]))
    };
    ($name:ident [ $($inner:tt),* ] ) => {
        make_result(stringify!($name), mactest!([$($inner),*]))
    };
    // Process single value. This is never matched?
    ($x:expr) => {
        $x.convert()
    };
}
//注意:u32用作示例结果类型。
//真正的代码试图创建一个更复杂的对象。
特色食品{
fn convert(&self)->u32;
}
fn生成结果(名称:&str,数据:Vec)->u32{
//此示例忽略名称,并生成无意义的结果
data.iter().fold(0,| a,&b | a+b)
}
#[宏_导出]
宏规则!麦考斯特{
([$($inner:expr),*])=>{{
让mut result=Vec::new();
$(
//处理每个元素。
结果.推送(mactest!($inner));
)*
结果
}};
($name:path[$($internal:tt),*])=>{
生成结果(stringify!($name),mactest!([$($inner),*]))
};
($name:ident[$($internal:tt),*])=>{
生成结果(stringify!($name),mactest!([$($inner),*]))
};
//处理单个值。是否从未匹配?
($x:expr)=>{
$x.convert()
};
}
宏的第一个匹配分支应该将列表中的每个元素与
路径/ident[items]
或末尾的单个项
相匹配。但是,当单个项目进入宏时,即
mactest,始终无法到达最后一个分支,错误:预期标识,找到“1”
!(1)

作为初学者,我的推理是宏有四种模式:
[expr*]
path[tt*]
ident[tt*]
expr
。当我将类似于1的内容传递到宏中时,我不明白为什么上面的任何模式都应该匹配/干扰


有人能解释为什么这不起作用吗?是否有一个解决方法来获得预期的结果?

宏规则是从第一个规则开始,然后从第一个规则开始执行。因此,如果您想防止在特殊情况下触发其他规则,则需要首先放置特殊情况规则


您的宏在常规情况下不起作用:。它会抱怨“预期的
]
之一,或者一个操作符,发现的
”除此之外,问题是外部调用匹配为
:expr
,这阻止了“特殊情况”规则的匹配。这只能通过增量解析来完成。让我困惑的是,在
mactest(1)
的情况下,我看不到前三条规则中的任何一条与
1
匹配。这些都是特殊情况,这就是为什么他们处于领先地位<代码>1既不是
标识
也不是
路径
。简而言之,错误消息真的让我很困惑@DK。在这种情况下,增量解析意味着什么?@porgarmingduod Bed time对我来说,但这(除其他外)在中进行了解释。简短版本:
宏规则解析器真的很笨,问题在于
1
不是标识符。具体的表述是不可能奏效的;见第2.3.1节。@DK。谢谢,这正是我需要的资源,来弥补我关于生锈宏的缺点。真不敢相信,当我在谷歌上搜索各种宏数据时,它竟然从未出现过。