当项目列表完全为空时, PGF\foreach
宏的行为与单个项目恰好为空时的行为不同。
\documentclass{article}
\usepackage{pgffor}
\begin{document}
\foreach \x in {,} {Hello}
\foreach \x in {} {How are you}
\end{document}
得出以下结果:
HelloHello
如果您正在编写以逗号分隔的字符串作为用户输入的宏,则此行为非常方便。这意味着您不必添加逻辑来检查是否真的有任何列表项。但是,PGF 手册中似乎没有提到这一点。它是否保证在 PGF/TikZ 的未来版本中不会改变?
答案1
正如评论中提到的,避免\foreach
使用空列表或列表项并自行进行测试会更有效。此外,在\foreach
迭代中完成的任何操作都必须全局执行,才能持续到循环结束。
可能有些软件包已经提供了此功能,但下面是一个可以实现的示例。它包含的内容比严格意义上需要的要多一些,只是为了提供更多信息输出:
\documentclass[border=0.125cm]{standalone}
\usepackage{xcolor}
\makeatletter
% \@ifnextchar is provided by LaTeX
\def\mycommand{\@ifnextchar[{\mycommand@}{\mycommand@[]}}
\def\mycommand@[#1]{%
\def\my@strings{#1}%
% \@empty already provided
\ifx\my@strings\@empty%
\my@nostrings% <- Don't really need this.
\let\my@next=\relax%
\else%
\let\my@next=\my@parsestrings%
\fi%
\my@next%
}
\def\my@parsestrings{%
\my@beforestrings% <- Don't really need this.
\expandafter\my@@parsestrings\my@strings,\my@parsestop,%
}
\def\my@parsestop{\my@parsestop}
\def\my@@parsestrings{\@ifnextchar x{\my@@@parsestrings}{\my@@@parsestrings}}
\def\my@@@parsestrings#1,{%
\def\my@string{#1}%
\ifx\my@string\my@parsestop%
\let\my@next=\my@@@@parsestrings%
\else%
\let\my@next=\my@@parsestrings%
\ifx\my@string\@empty%
\else%
% Process string
\my@processstring{#1}%
\fi%
\fi%
\my@next%
}
\def\my@@@@parsestrings{%
\my@afterstrings% <- Possibly don't need this.
}
\def\my@nostrings{%
{\tt No strings}%
}
\def\my@beforestrings{%
{\tt Processing strings}%
}
\def\my@afterstrings{%
{\tt\\ Finished strings}%
}
\def\my@processstring#1{%
{\tt\\\hskip0.25in[string:`#1']}%
}
\makeatother
\begin{document}
\begin{minipage}{2in}
\mycommand
\color{red}
\mycommand[]
\color{green!50!black}
\mycommand[a,b,c]
\color{blue}
\mycommand[a,,b,c,,]
\color{purple}
\mycommand[ a, , b, c, ,]
\end{minipage}
\end{document}