英文:
Generalizing `macro_rules!` matches
问题
我有一个宏,根据提供的参数以稍微不同的方式调用另一个宏。
macro_rules! do_things {
($($e:expr),*) => { ... }
}
macro_rules! do_more_things {
($($e:expr),* ; $val1:expr, $cond:expr) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1, $cond);
}
}
};
($($e:expr),* ; $val1:expr, $val2:expr, $cond:expr) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1, $val2);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1, $val2, $cond);
}
}
};
}
如何泛化以消除两个非常相似的分支?如果有帮助的话,此处的 do_things!(a, b);
相当于 do_things!(a); do_things!(b)
。
英文:
I have a macro that calls another macro in a slightly different way based on the arguments provided.
macro_rules! do_things {
($($e:expr),*) => { ... }
}
macro_rules! do_more_things {
($($e:expr),* ; $val1:expr, $cond:expr) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1, $cond);
}
}
};
($($e:expr),* ; $val1:expr, $val2:expr, $cond:expr) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1, $val2);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1, $val2, $cond);
}
}
};
}
How can I generalize it to eliminate two very similar branches?
If it helps, do_things!(a, b);
in this case is equivalent to do_things!(a); do_things!(b)
.
答案1
得分: 1
不可能完全按照这种调用方式实现,但你可以重新排列参数,使条件在所有值之前出现:
macro_rules! do_more_things {
($cond:expr, $($e:expr),* ; $val1:expr $(, $val2:expr)? ) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1 $(, $val2)?);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1 $(, $val2)?, $cond);
}
}
};
}
或者,你可以像 @BallpointBen 建议的那样,更改条件和值之间的分隔符为某个明显的内容。
英文:
It's not possible with exactly that invocation, but you can either rearrange the arguments so that the condition comes before all the values:
macro_rules! do_more_things {
($($e:expr),* ; $cond:expr, $val1:expr $(, $val2:expr)? ) => {
{
do_things!($($e),*);
if $cond {
do_things!(MAGIC_CONST_1 | $val1 $(, $val2)?);
call_something($cond);
} else {
do_things!(MAGIC_CONST_2 | $val1 $(, $val2)?, $cond);
}
}
};
}
alternatively you can change the separator between the condition and the values to something distinct like @BallpointBen suggests
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论