我想定义一个宏,将其内容输入到 tikz\foreach
语句中,例如:
\newcommand\Macro[1]{ \foreach \x in {#1} {x=\x.} }
然后将其用作\Macro{1,2,3,4}
。有时,我想给它“空”参数,例如\Macro{,,,4,5,5}
。我希望能够检测到“空”参数并在这种情况下执行不同的操作。我认为类似下面的操作会起作用:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize{\x}\relax Empty!
\else x=\x.
\fi
}
}
但由于某种原因,这不能检测到空参数,而是产生:
我尝试了许多其他方法,例如\x
先扩展,但我还没有找到任何有效的方法。
有人能找到这样做的方法吗?
[我的真实代码正在生成一个tikzpicture
环境,所以我真的想\foreach
从`tikz`中使用。]
答案1
答案2
这个问题在宏中源于问题:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize{\x}\relax Empty!
\else x=\x.
\fi
}
}
是\detokenize
不展开其参数并返回两个标记\
和x
。通过添加可以解决这个问题\expandafter
:
\detokenize\expandafter{\x}
完整宏:
\newcommand\Macro[1]{%
\foreach \x in {#1} {
\if\relax\detokenize\expandafter{\x}\relax Empty!
\else x=\x.
\fi
}
}
答案3
强制性expl3
答案(注意到之后将\detokenize\expandafter{\x}
是解决方案):
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\blankTF}{mmm}
{% #1 = text to test, #2 = blank case, #3 = non blank case
\str_if_eq_x:nnTF { #1 } { } { #2 } { #3 }
}
\NewDocumentCommand{\lforeach}{O{,}mm}
{% #1 = delimiter, #2 = list, #3 = code
\seq_set_split:Nnn \l_andrew_foreach_seq { #1 } { #2 }
\seq_map_inline:Nn \l_andrew_foreach_seq { #3 }
}
\ExplSyntaxOff
\newcommand\Macro[1]{%
\lforeach{#1}{%
\blankTF{##1}{Empty!}{$|$##1$|$.}
}
}
\begin{document}
\lforeach[-]{a-b--\texttt{c}}{%
\blankTF{#1}{Empty!}{$|$#1$|$.}
}
\lforeach{, ,,4, 5 ,5}{%
\blankTF{#1}{Empty!}{$|$#1$|$.}
}
\Macro{, ,,4, 5 ,5}
\end{document}
循环中的当前项用 表示(在 的定义中#1
必须变成)。##1
\Macro