![当创建元组的语法是预定义的并且无法更改时,模拟“元组”数据结构](https://linux22.com/image/247386/%E5%BD%93%E5%88%9B%E5%BB%BA%E5%85%83%E7%BB%84%E7%9A%84%E8%AF%AD%E6%B3%95%E6%98%AF%E9%A2%84%E5%AE%9A%E4%B9%89%E7%9A%84%E5%B9%B6%E4%B8%94%E6%97%A0%E6%B3%95%E6%9B%B4%E6%94%B9%E6%97%B6%EF%BC%8C%E6%A8%A1%E6%8B%9F%E2%80%9C%E5%85%83%E7%BB%84%E2%80%9D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.png)
假设我有一个接受三个参数的宏\createcontact
。现在,我不想在扩展期间使用这些参数,而是想将它们单独保存以供以后使用和检索。上述宏在以下上下文中使用:
\newcommand{\myfirstauthor}{\createcontact{Alice}{Munich}{Germany}}
\newcommand{\mysecondauthor}{\createcontact{Bob}{London}{United Kingdom}}
% and so forth
我该如何实现\createcontact
才能从 等中提取传递给它的各个参数\myfirstauthor
?\mysecondauthor
提取的代码会是什么样子?换句话说,我需要如何定义\createcontact
一个宏,\extractsecond
以便\extractsecond\myfirstauthor
将其扩展为Munich
?
编辑:请注意,只有 的定义\createcontact
可以调整,而 等的定义则不能调整\myfirstauthor
。\mysecondauthor
也就是说,上述使用模式必须保持“原样”。
进行此练习的原因是上述模式在用户文档中随处可见。我想对参数进行更复杂的处理,\createcontact
而不是简单地使用它们一次在宏中。(例如,我想Munich
在一个上下文中使用,Germany
在另一个上下文中使用。)
根据 Peter 的要求,这里有一个“可编译”的示例,其中有占位符而不是我感兴趣的命令:
\documentclass{article}
% HOW TO IMPLEMENT THIS?
\newcommand{\createcontact}[3]{...}
\newcommand{\extractfirst}[1]{...}
\newcommand{\extractsecond}[1]{...}
\newcommand{\extractthird}[1]{...}
% HOW TO IMPLEMENT THIS?
% DO NOT CHANGE OR MOVE THIS
\newcommand{\myfirstauthor}{\createcontact{Alice}{Munich}{Germany}}
\newcommand{\mysecondauthor}{\createcontact{Bob}{London}{United Kingdom}}
% DO NOT CHANGE OR MOVE THIS
\begin{document}
\extractfirst{\myfirstauthor} lives in \extractsecond{\myfirstauthor}
which is located in \extractthird{\myfirstauthor};
this may or may not be true for \extractfirst{\mysecondauthor}.
\end{document}
答案1
使用 lambda 列表:
\documentclass{minimal}
\usepackage{lambda} % http://www.ctan.org/pkg/lambda-lists
%
\def\createcontact#1#2#3{\Listize[#1,#2,#3]}
\let\extractfirst\Head
\def\extractsecond#1{\extractfirst{\Tail{#1}}}
\def\extractthird#1{\extractsecond{\Tail{#1}}}
%
\newcommand{\myfirstauthor}{\createcontact{Alice}{Munich}{Germany}}
\newcommand{\mysecondauthor}{\createcontact{Bob}{London}{United Kingdom}}
%
\begin{document}
\extractfirst{\myfirstauthor} lives in \extractsecond{\myfirstauthor}
which is located in \extractthird{\myfirstauthor};
(or \Head{\Tail{\Tail{\myfirstauthor}}},
or \Head{\Reverse{\myfirstauthor}})
this may or may not be true for \extractfirst{\mysecondauthor}.
\end{document}
答案2
基本解决方案:
如果没有更多细节,很难知道像这样简单的事情是否适合您:您调用\myfirstauthor{Kenobi}{General}{1138}
,然后要访问每个成员,您只需引用\myfirstauthorName
、\myfirstauthorRank
和\myfirstauthorSerialNum
:
\documentclass{article}
\newcommand{\myfirstauthor}[3]{%
\newcommand{\myfirstauthorName}{#1}%
\newcommand{\myfirstauthorRank}{#2}%
\newcommand{\myfirstauthorSerialNum}{#3}%
}
\begin{document}
\myfirstauthor{Kenobi}{General}{1138}
The details of the first author are:
\medskip
\begin{tabular}{rl}
Name: & \myfirstauthorName\\
Rank: & \myfirstauthorRank\\
Serial Number: & \myfirstauthorSerialNum
\end{tabular}
\end{document}
替代解决方案:
您可以指定宏的第一个参数来区分它们,而不是创建单独的宏列表,等等\myfirstauthor
。这样可以得到更灵活的解决方案,因为您可以动态创建宏。因此,使用此解决方案,您可以使用(或省略,因为这是默认值),但其他宏可以简单地通过定义,并像上面的例子一样访问,以得出:\mysecondauthor
\myauthor
\myauthor[first]{Kenobi}{General}{1138}
first
\myauthor[second]{Dooku}{Count}{66}
要创建另一个,您只需使用\myauthor[third]{}{}{}
,等等......
\documentclass{article}
\newcommand{\myauthor}[4][first]{%
\expandafter\newcommand\csname my#1authorName\endcsname{#2}%
\expandafter\newcommand\csname my#1authorRank\endcsname{#3}%
\expandafter\newcommand\csname my#1authorSerialNum\endcsname{#4}%
}
\begin{document}
\myauthor{Kenobi}{General}{1138}
\myauthor[second]{Dooku}{Count}{66}
The details of the first two authors are:
\medskip
\begin{tabular}{rll}
Name: & \myfirstauthorName & \mysecondauthorName\\
Rank: & \myfirstauthorRank & \mysecondauthorRank\\
Serial Number: & \myfirstauthorSerialNum & \mysecondauthorSerialNum
\end{tabular}
\end{document}
根据给定的 MWE 解决方案:
通过修改限制,您可以使用基于 if或\AtBeginDocument
的定义来更改调用 :\createcontact
\myfirstauthor
\mysecondauthor
\documentclass{article}
% HOW TO IMPLEMENT THIS?
\newcommand{\createcontact}[3]{}
\newcommand{\extractfirst}[1]{\csname #1Name\endcsname}
\newcommand{\extractsecond}[1]{\csname #1City\endcsname}
\newcommand{\extractthird}[1]{\csname #1Country\endcsname}
\newcommand{\myfirstauthorName}{}%
\newcommand{\myfirstauthorCity}{}%
\newcommand{\myfirstauthorCountry}{}%
\newcommand{\CreateFirstContact}[3]{%
\renewcommand{\myfirstauthorName}{#1}%
\renewcommand{\myfirstauthorCity}{#2}%
\renewcommand{\myfirstauthorCountry}{#3}%
}
\newcommand{\mysecondauthorName}{}%
\newcommand{\mysecondauthorCity}{}%
\newcommand{\mysecondauthorCountry}{}%
\newcommand{\CreateSecondContact}[3]{%
\renewcommand{\mysecondauthorName}{#1}%
\renewcommand{\mysecondauthorCity}{#2}%
\renewcommand{\mysecondauthorCountry}{#3}%
}
\AtBeginDocument{%
\let\OldFirstAuthor\myfirstauthor
\let\OldSecondAuthor\mysecondauthor
\renewcommand{\myfirstauthor}{\let\createcontact\CreateFirstContact\OldFirstAuthor}
\renewcommand{\mysecondauthor}{\let\createcontact\CreateSecondContact\OldSecondAuthor}
\myfirstauthor
\mysecondauthor
}
% HOW TO IMPLEMENT THIS?
% DO NOT CHANGE THIS
\newcommand{\myfirstauthor}{\createcontact{Alice}{Munich}{Germany}}
\newcommand{\mysecondauthor}{\createcontact{Bob}{London}{United Kingdom}}
\begin{document}
\noindent
\extractfirst{myfirstauthor} lives in \extractsecond{myfirstauthor}
which is located in \extractthird{myfirstauthor};
this may or may not be true for \extractfirst{mysecondauthor}.
\end{document}
答案3
感谢 Bruno Le Floch 提出这个想法,以下是我认为“对我有用”的做法:
\documentclass{standalone}
% ONE POSSIBLE SOLUTION
\newcommand{\createcontact}[3]{}
\newcommand{\extractfirst}[1]{\renewcommand{\createcontact}[3]{##1}#1}
\newcommand{\extractsecond}[1]{\renewcommand{\createcontact}[3]{##2}#1}
\newcommand{\extractthird}[1]{\renewcommand{\createcontact}[3]{##3}#1}
% ONE POSSIBLE SOLUTION
% DO NOT CHANGE THIS
\newcommand{\myfirstauthor}{\createcontact{Alice}{Munich}{Germany}}
\newcommand{\mysecondauthor}{\createcontact{Bob}{London}{United Kingdom}}
% DO NOT CHANGE THIS
\begin{document}
\extractfirst{\myfirstauthor} lives in \extractsecond{\myfirstauthor}
which is located in \extractthird{\myfirstauthor};
this may or may not true for \extractfirst{\mysecondauthor}.
\end{document}