如何將 \toks 與 \foreach 一起使用

如何將 \toks 與 \foreach 一起使用

我想用它\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

如果您正在使用pgfkeysand 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}

相關內容