我写了下面的代码
\documentclass{article}
\makeatletter
\newtoks\a@toks
\newtoks\b@toks
\newcounter{a@counter}%
\newcounter{b@counter}%
\setcounter{a@counter}{0}%
\setcounter{b@counter}{0}%
\newcommand{\aAdd}[1]{%
\ifnum\thea@counter>0\a@toks=\expandafter{\the\a@toks {#1}}%
\else\a@toks=\expandafter{\the\a@toks {#1}}%
\fi
\stepcounter{a@counter}%
}
\newcommand{\reset}{%
\setcounter{a@counter}{0}%
\a@toks={}%
}
\newcommand{\bexp}{%
\ifnum\theb@counter>0\b@toks=\expandafter{\the\b@toks, (\the\a@toks)}%
\else\b@toks=\expandafter{\the\b@toks (\the\a@toks) }%
\fi
\stepcounter{b@counter}%
\setcounter{a@counter}{0}%
\a@toks=\noexpand{}%
}
\newcommand{\print}{%
\the\b@toks%
}
\makeatother
\begin{document}
Hello World!\\[3cm]
\aAdd{a}
\aAdd{b}
\bexp
\aAdd{c}
\print
\end{document}
我想要做的事情如下:\aAdd
我将一些元素添加到列表中,具体来说,在这个例子中
\aAdd{a}
\aAdd{b}
我期望\a@toks
等于ab
。然后我将其刷新到另一个标记中,因此我期望\b@toks
等于ab
。问题是当命令
\a@toks={}
执行后,即使\b@toks
继续跟随 \a@toks
,这样,当我执行
\aAdd{c}
\b@toks
具有价值c
。
我想,一旦设置\b@toks = \a@toks
为仅设置的值\b@toks
,这样,当我重新定义时\a@toks
,\b@toks
继续具有前面的值(在本例中ab
)。
谁能帮我?
答案1
\expandafter
不扩大一切之后,只需添加以下标记。此外,由于它似乎b@counter
衡量了添加到的内容\b@toks
,因此我认为没有必要
\ifnum...
\else\b@toks=\expandafter{\the\b@toks (\the\a@toks) }
\fi
您想要\b@toks
在其中添加(一个空的)内容。
我认为以下内容会产生您想要的结果(我对其进行了一些清理):
\documentclass{article}
\makeatletter
\newtoks\a@toks
\newtoks\b@toks
\newcounter{b@counter}%
\newcounter{a@counter}[b@counter]%
\newcommand{\aAdd}[1]{%
\ifnum\value{a@counter}>0 \a@toks=\expandafter{\the\a@toks {#1}}%
\else\a@toks=\expandafter{\the\a@toks {#1}}%
\fi
\stepcounter{a@counter}%
}
\newcommand{\reset}{%
\setcounter{a@counter}{0}%
\a@toks={}%
}
\newcommand{\bexp}{%
\ifnum\value{b@counter}>0
\edef\x{\noexpand\b@toks={\the\b@toks, (\the\a@toks)}}%
\else
\edef\x{\noexpand\b@toks={(\the\a@toks)}}%
\fi
\x
\stepcounter{b@counter}%
\a@toks={}%
}
\newcommand{\print}{%
\the\b@toks%
}
\makeatother
\begin{document}
Hello World!
\bigskip
\aAdd{a}% \a@toks = {a}
\aAdd{b}% \a@toks = {a}{b}
\bexp% \a@toks = {}, \b@toks = {a}{b}
\aAdd{c}% \a@toks = {c}
\print% \b@toks
\end{document}
可以使用
\b@toks=\expandafter{\expandafter(\the\a@toks)}
确保\a@toks
在将其插入之前已展开\b@toks
。但是,我选择\b@toks
使用一种\edef\x{...}\x
方法确保在将其添加到之前所有内容都已展开。
如果留下不想要的东西\x
是一个问题,您可以使用以下定义\bexp
:
\newcommand{\bexp}{%
\begingroup
\ifnum\value{b@counter}>0
\edef\x{\endgroup\noexpand\b@toks={\the\b@toks, (\the\a@toks)}}%
\else
\edef\x{\endgroup\noexpand\b@toks={(\the\a@toks)}}%
\fi
\x
\stepcounter{b@counter}%
\a@toks={}%
}
答案2
Werner 的分析非常好。下面是使用 和 的替代实现xparse
。expl3
请注意,您可以将项之间的分隔符定义为可选参数\print
(默认为“逗号空格”)。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\aAdd}{m}
{
\mapo_aadd:n { #1 }
}
\NewDocumentCommand{\bexp}{}
{
\mapo_bexp:
}
\NewDocumentCommand{\reset}{}
{
\mapo_reset:
}
\NewDocumentCommand{\print}{O{,~}}
{
\mapo_print:n { #1 }
}
\tl_new:N \l_mapo_a_tl
\seq_new:N \l_mapo_b_seq
\cs_new_protected:Nn \mapo_aadd:n
{
\tl_put_right:Nn \l_mapo_a_tl { #1 }
}
\cs_new_protected:Nn \mapo_bexp:
{
\seq_put_right:Nx \l_mapo_b_seq { ( \exp_not:V \l_mapo_a_tl ) }
\mapo_reset:
}
\cs_new_protected:Nn \mapo_reset:
{
\tl_clear:N \l_mapo_a_tl
}
\cs_new:Nn \mapo_print:n
{
\seq_use:Nn \l_mapo_b_seq { #1 }
}
\ExplSyntaxOff
\begin{document}
\noindent
Hello World!\\
\aAdd{a}\aAdd{b}\bexp\aAdd{c}%
\print\\
\bexp
\print[---]
\end{document}