我想通过使用例如 a 来顺序转换 tikz 中的对象,\foreach
并为每个步骤迭代后的结果定义一个宏。下面是我想做的一个简单示例。在我看来,结果应该是 (2,0) 处的“X”。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\gdef\Stepi{\node at (0,0) {X};}
\newcount\Counter
\newcount\CounterOneLess
\Counter=1
\CounterOneLess=0
\foreach \i in {2,3}
{
\global\advance\Counter by1
\global\advance\CounterOneLess by1
\expandafter\gdef\csname Step\romannumeral\Counter\endcsname
{
\protect\begin{scope}[shift={(1,0)}]
\csname Step\romannumeral\CounterOneLess\endcsname
\protect\end{scope}
}
}
\Stepiii
\end{tikzpicture}
\end{document}
但是,当我尝试运行 pdflatex 时,出现错误,提示 TeX 容量(更具体地说是允许的分组级别数)已超出。我猜这个错误意味着我无意中导致了无限循环,并且它与我对扩展的误解有关。有没有办法让这个概念发挥作用?
如果有帮助的话,如果我更换
\csname Step\romannumeral\CounterOneLess\endcsname
在范围环境中使用\Stepi
。结果为预期位置处的 X(即,在这种情况下为 (1,0))。当然,进行这种替换违背了目的。
答案1
\xdef
而不是在循环\gdef
内部\foreach
扩展定义文本和当前计数器值。\noexpand
而不是\protect
阻止内部的扩展\xdef
。\protect
仅适用于 LaTeX 宏(\protected@edef
,...)。
修正示例:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\gdef\Stepi{\node at (0,0) {X};}
\newcount\Counter
\newcount\CounterOneLess
\Counter=1
\CounterOneLess=0
\foreach \i in {2,3}
{
\global\advance\Counter by1
\global\advance\CounterOneLess by1
\expandafter\xdef\csname Step\romannumeral\Counter\endcsname
{
\noexpand\begin{scope}[shift={(1,0)}]
\expandafter\noexpand\csname Step\romannumeral\CounterOneLess\endcsname
\noexpand\end{scope}
}
}
\Stepiii
\end{tikzpicture}
\end{document}
这里不需要计数器业务,因为它\foreach
已经提供了所有需要的功能:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\gdef\Stepi{\node at (0,0) {X};}
\foreach \i [evaluate=\i as \ioneless using int(\i-1)] in {2,3}
{
\expandafter\xdef\csname Step\romannumeral\i\endcsname
{
\noexpand\begin{scope}[shift={(1,0)}]
\expandafter\noexpand\csname Step\romannumeral\ioneless\endcsname
\noexpand\end{scope}
}
}
\Stepiii
\end{tikzpicture}
\end{document}
答案2
使用更少的\noexpand
token:
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DefineStep}{m}
{
\paige_definestep:xx { \int_to_roman:n { #1 } } { \int_to_roman:n { #1 - 1 } }
}
\cs_new_protected:Nn \paige_definestep:nn
{
\cs_gset:cpn { Step#1 }
{
\begin{scope}[shift={(1,0)}]
\use:c { Step#2 }
\end{scope}
}
}
\cs_generate_variant:Nn \paige_definestep:nn { xx }
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\gdef\Stepi{\node at (0,0) {X};}
\foreach \i in {2,3} { \DefineStep{\i} }
\Stepi \Stepii \Stepiii
\end{tikzpicture}
\footnotesize
\texttt{\meaning\Stepi}
\texttt{\meaning\Stepii}
\texttt{\meaning\Stepiii}
\end{document}