当传递逗号分隔的列表时,逗号会被忽略,即列表变成单个项目,我似乎找不到阻止这种情况的方法。我应该怎么做才能使附加代码中的 TEST C 实现“提取”列表中项目的预期结果?
\documentclass{article}
\usepackage{pgffor}
\newcommand{\setstr}[2]{\expandafter\def\csname#1\endcsname{#2}}
\newcommand{\getstr}[1]{\csname#1\endcsname}
\newcommand{\PROCESS}[1]
{
The list items are:
\foreach \i in {#1}
{
(\i)
}
}
\newcommand{\SETC}[2]{\setstr{C#1}{#2}}
\newcommand{\RUN}[1]{
\expandafter\PROCESS\expandafter{\getstr{C#1}}
}
\begin{document}
%
% The following works
%
\noindent{TEST A:}
\PROCESS{a,b,c,d}
\newline
%
% and the following also works
%
\noindent{TEST B:}
\newcommand{\A}{a,b,c,d}
\expandafter\PROCESS\expandafter{\A}
\newline
%
% but this does not work
%
\noindent{TEST C:}
\SETC{1}{a,b,c,d}%
\RUN{1}%
\newline
\end{document}
答案1
正如 Qrrbrbirlbel 在评论中所说,这是一个扩展问题;\getstr
需要三个扩展步骤,而不仅仅是一个。
\documentclass{article}
\usepackage{pgffor}
\newcommand{\setstr}[2]{\expandafter\def\csname#1\endcsname{#2}}
\newcommand{\getstr}[1]{\csname#1\endcsname}
\newcommand{\PROCESS}[1]{%
The list items are:
\foreach \i in {#1}
{%
(\i)
}%
}
\newcommand{\SETC}[2]{\setstr{C#1}{#2}}
\makeatletter
\newcommand{\RUN}[1]{%
\begingroup\protected@edef\x{\endgroup\protect\PROCESS{\getstr{C#1}}}\x
}
\makeatother
\begin{document}
%
% The following works
%
\noindent{TEST A:}
\PROCESS{a,b,c,d}
%
% and the following also works
%
\newcommand{\A}{a,b,c,d}
\noindent{TEST B:}
\expandafter\PROCESS\expandafter{\A}
%
% also this works
%
\SETC{1}{a,b,c,d}
\noindent{TEST C:}
\RUN{1}
\end{document}
稍微不同的方法可以更好地保留逗号分隔列表的结构。
\documentclass{article}
\usepackage{pgffor}
\newcommand{\setstr}[2]{\expandafter\def\csname#1\endcsname{\unexpanded{#2}}}
\newcommand{\getstr}[1]{\csname#1\endcsname}
\newcommand{\PROCESS}[1]{%
The list items are:
\foreach \i in {#1}
{%
(\i)
}%
}
\newcommand{\SETC}[2]{\setstr{C#1}{#2}}
\newcommand{\RUN}[1]{%
\begingroup\edef\x{\endgroup
\noexpand\PROCESS{\getstr{C#1}}}\x
}
\begin{document}
%
% The following works
%
\noindent{TEST A:}
\PROCESS{a,b,c,d}
%
% and the following also works
%
\newcommand{\A}{a,b,c,d}
\noindent{TEST B:}
\expandafter\PROCESS\expandafter{\A}
%
% also this works
%
\SETC{1}{a,b,c,\textbf{d}}
\noindent{TEST C:}
\RUN{1}
\getstr{C1}
\end{document}
答案2
虽然 OP 可能只对 LaTeX 解决方案感兴趣,但在这里我将提供一个 ConTeXt 解决方案。
该命令\processcommacommand
有两个参数。第一个参数是逗号分隔的列表,可以是宏,第二个参数是用于处理列表项的宏。示例:
\define[1]\doprocess
{(#1)}
\define\somelist
{foo, bar, baz}
\starttext
\processcommacommand
[alpha, \math{\beta}, gamma]
\doprocess
\processcommacommand
[\somelist]
\doprocess
\expandafter\processcommacommand\expandafter
[\somelist]
\doprocess
\stoptext