一般化`macro_rules!`匹配

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

Generalizing `macro_rules!` matches

问题

我有一个宏,根据提供的参数以稍微不同的方式调用另一个宏。

  1. macro_rules! do_things {
  2. ($($e:expr),*) => { ... }
  3. }
  4. macro_rules! do_more_things {
  5. ($($e:expr),* ; $val1:expr, $cond:expr) => {
  6. {
  7. do_things!($($e),*);
  8. if $cond {
  9. do_things!(MAGIC_CONST_1 | $val1);
  10. call_something($cond);
  11. } else {
  12. do_things!(MAGIC_CONST_2 | $val1, $cond);
  13. }
  14. }
  15. };
  16. ($($e:expr),* ; $val1:expr, $val2:expr, $cond:expr) => {
  17. {
  18. do_things!($($e),*);
  19. if $cond {
  20. do_things!(MAGIC_CONST_1 | $val1, $val2);
  21. call_something($cond);
  22. } else {
  23. do_things!(MAGIC_CONST_2 | $val1, $val2, $cond);
  24. }
  25. }
  26. };
  27. }

如何泛化以消除两个非常相似的分支?如果有帮助的话,此处的 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.

  1. macro_rules! do_things {
  2. ($($e:expr),*) => { ... }
  3. }
  4. macro_rules! do_more_things {
  5. ($($e:expr),* ; $val1:expr, $cond:expr) => {
  6. {
  7. do_things!($($e),*);
  8. if $cond {
  9. do_things!(MAGIC_CONST_1 | $val1);
  10. call_something($cond);
  11. } else {
  12. do_things!(MAGIC_CONST_2 | $val1, $cond);
  13. }
  14. }
  15. };
  16. ($($e:expr),* ; $val1:expr, $val2:expr, $cond:expr) => {
  17. {
  18. do_things!($($e),*);
  19. if $cond {
  20. do_things!(MAGIC_CONST_1 | $val1, $val2);
  21. call_something($cond);
  22. } else {
  23. do_things!(MAGIC_CONST_2 | $val1, $val2, $cond);
  24. }
  25. }
  26. };
  27. }

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

不可能完全按照这种调用方式实现,但你可以重新排列参数,使条件在所有值之前出现:

  1. macro_rules! do_more_things {
  2. ($cond:expr, $($e:expr),* ; $val1:expr $(, $val2:expr)? ) => {
  3. {
  4. do_things!($($e),*);
  5. if $cond {
  6. do_things!(MAGIC_CONST_1 | $val1 $(, $val2)?);
  7. call_something($cond);
  8. } else {
  9. do_things!(MAGIC_CONST_2 | $val1 $(, $val2)?, $cond);
  10. }
  11. }
  12. };
  13. }

或者,你可以像 @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:

  1. macro_rules! do_more_things {
  2. ($($e:expr),* ; $cond:expr, $val1:expr $(, $val2:expr)? ) => {
  3. {
  4. do_things!($($e),*);
  5. if $cond {
  6. do_things!(MAGIC_CONST_1 | $val1 $(, $val2)?);
  7. call_something($cond);
  8. } else {
  9. do_things!(MAGIC_CONST_2 | $val1 $(, $val2)?, $cond);
  10. }
  11. }
  12. };
  13. }

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:

确定