一般化`macro_rules!`匹配

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

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

huangapple
  • 本文由 发表于 2023年7月13日 19:22:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76678812.html
匿名

发表评论

匿名网友

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

确定