我想用\foreach
以下代码替换:
\def\x{0}
\edef\y{\x}
\xdef\z{(b\y)}
\def\x{1}
\edef\y{\x}
\xdef\w{\z(b\y)}
\def\x{2}
\edef\y{\x}
\xdef\z{\w(b\y)}
\def\x{3}
\edef\y{\x}
\xdef\w{\z(b\y)}
\w
目的是使用宏获得此结果: (b0)(b1)(b2)(b3)
我得到了结果\toks
但也许可以避免这种情况。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\makeatletter
\toksdef\toks@=0 % ?
\toksdef\toks@@=1 %
\xdef\tmp{}%
\foreach \x in {0,1,2,3}{%
\toks@\expandafter{\x}%
\toks@@\expandafter{\tmp}%
\xdef\tmp{\the\toks@@(b\the\toks@)}%
}
\makeatother
\tmp
\end{document}
我认为这段代码不太好。没有外部包的情况下,获取结果的更好方法是什么?
答案1
LaTeX 内核\@for
不支持以下组\foreach
:
\def\tmp{}
\@for\next:=0,1,2,3\do{\edef\tmp{\tmp(b\next)}}
在您的代码中不需要\toks
:
\foreach \x in {0,1,2,3}{%
\xdef\tmp{\tmp(b\x)}%
}
也可以。
但是,如果这些项目是“危险的”,因为它们无法存活\edef
(如\textbf
或其他类似的标记),则使用标记寄存器是避免完全扩展的必要条件,您的方法很好。最好使用\toks2
而不是\toks1
进行本地分配,因此您应该这样做
\toksdef\toks@@=2
答案2
使用一个大的包循环结构对于这个来说确实是过度的,因为一个\def
就足够了
\def\x#1{\ifnum\numexpr#1\relax>0 \x{#1-1}\fi(b\the\numexpr#1\relax)}
\typeout{\x{3}}
生产
(b0)(b1)(b2)(b3)
答案3
如果您正在使用pgfkeys
(处理程序pgffor
内部使用.list
),那么您可以简单地使用该.list
处理程序。
如果只需要序列(b0)(b…)b(3)
排版,可以设置一 .code
键并将该键与.list
处理程序一起使用。(→ do
)
但是,如果您想要一个可扩展的宏,则该宏必须是固定的(→ doo
,相当于\foreach \x in {0,...,3}{\xdef\tmp{\tmp(b\x)}}
)或者您需要多个键(→ dooo
,更灵活)。
代码
\documentclass{article}
\usepackage{pgfkeys,pgffor}
\makeatletter
\pgfkeys{/alain/do/.code=(b#1)}
\pgfkeys{/alain/doo/.code=\edef\tmp{\tmp(b#1)}}
\pgfkeys{/alain/dooo ini/.code=\let\qrr@doo@temp\pgfutil@empty,
/alain/dooo/.code=\edef\qrr@doo@temp{\qrr@doo@temp(b#1)},
/alain/dooo set/.code=\let#1\qrr@doo@temp}
\makeatletter
\begin{document}
\pgfkeys{/alain/do/.list={0,...,3}}
\def\tmp{}
\pgfkeys{/alain/doo/.list={0,...,3}}
\tmp
\pgfkeys{/alain/.cd,
dooo ini,
dooo/.list={0,...,3},
dooo set=\myTemp}
\myTemp
\end{document}