如何将 \def 参数传递给内部命令(StrSubstitute)?

如何将 \def 参数传递给内部命令(StrSubstitute)?

我正在尝试创建 2 个宏来模拟 Java 中的数组列表。我正在使用xstring StrSubstitute为此,但我遇到了一个问题。下面是代码,它有点长,因为它包含宏和测试文档。

当前活动的 StrSubstitute 行正在工作,因为它明确指定了替换的接收者(\Cities)。

\csname #1\endcsname另一方面,第一行注释掉的 StrSubstitute 行(使用)导致以下 TeX 错误:

! Extra \endcsname.
<argument> \csname testAL\endcsname 

l.21 \addElementToArrayList{testAL}{Paris}

第二行注释(仅使用#1)导致以下错误:

! Missing control sequence inserted.
<inserted text> 
            \inaccessible 
l.21 \addElementToArrayList{testAL}{Paris}

我尝试阅读一些TeX资源,但无法使其工作,并且发现了很多可能性(\def,,...)\edef\noexpand

\documentclass[a4paper,10pt]{article}
\usepackage[utf8x]{inputenc}
\RequirePackage{xstring}    %will use this package for the internal list structure

\def\ARRAYENDSENTINEL{@@}   %indicates array end
\def\ARRAYSEPARATOR{,}      %element separator

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Macro to create a new list:
%Parameters: <list name>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\newArrayList#1{%
      \expandafter\def\csname#1\endcsname{\ARRAYENDSENTINEL}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Macro to append element on a list:
%Parameters: <list name>, <element to add>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\addElementToArrayList#1#2{
  \StrSubstitute[1]{\csname #1\endcsname}{\ARRAYENDSENTINEL}{\ARRAYSEPARATOR #2\ARRAYENDSENTINEL}[\Cities] %working
  %\StrSubstitute[1]{\csname #1\endcsname}{\ARRAYENDSENTINEL}{\ARRAYSEPARATOR #2\ARRAYENDSENTINEL}[\csname #1\endcsname] %NOT working!
  %\StrSubstitute[1]{\csname #1\endcsname}{\ARRAYENDSENTINEL}{\ARRAYSEPARATOR #2\ARRAYENDSENTINEL}[#1] %NOT working either!
}

%opening
\title{Testing ArrayList}
\author{}

\begin{document}
\maketitle

\newArrayList{Cities}

Contents of Cities: \textbf{[\Cities]}

\addElementToArrayList{Cities}{Paris}

Contents of Cities: \textbf{[\Cities]}

\addElementToArrayList{Cities}{London}

Contents of Cities: \textbf{[\Cities]}

\addElementToArrayList{Cities}{Rome}

Contents of Cities: \textbf{[\Cities]}


\end{document}

答案1

您不能在需要的\csname foo\endcsname位置使用,例如将重新定义为参数文本和替换文本。您需要先扩展一次才能构建。原语在这里可以帮助您。它会在以下标记后扩展标记(=~ 宏或字符)一次。因此将扩展为,以便定义。这里的一个问题是,如果您想在长行的末尾扩展,则可能需要多次。\foo\def\csname foo\endcsname{...}\csnamefoo\endcsname...\csname foo\endcsname\foo\expandafter\expandafter\def\csname foo\endcsname{...}\def\foo{...}\foo\expandafter\csname ...\endcsname

在这种情况下,最好将该行存储在临时宏中:

\def\addElementToArrayList#1#2{%
  \begingroup
  \def\temp{\endgroup\StrSubstitute[1]{\csname #1\endcsname}{\ARRAYENDSENTINEL}{\ARRAYSEPARATOR #2\ARRAYENDSENTINEL}[}%
  \expandafter\temp\csname #1\endcsname]%
}

或者扩展\csname ...\endcsname第一个宏并将其提供给第二个宏:

\def\addElementToArrayList#1{%
  \expandafter\addElementToArrayListX\expandafter{\csname #1\endcsname}%
}

\def\addElementToArrayListX#1#2{%
  \StrSubstitute[1]{#1}{\ARRAYENDSENTINEL}{\ARRAYSEPARATOR #2\ARRAYENDSENTINEL}[#1]%
}

这里我们\expandafter连续使用两个 s 来“跳过”\addElementToArrayListX{。请注意,仅使用第二个宏读取第二个参数是完全可以的。

相关内容