我正在尝试为 AIAA 包编写一个新环境(主要是为了好玩/学习)。我想采用作者部分:
\author{
First A. Author\thanks{Job Title, Department, Address, and AIAA Member Grade.}
\ and Second B. Author\thanksibid{1}\\
{\normalsize\itshape
Business or Academic Affiliation, City, Province, Zipcode, Country}\\
\and
Third C. Author\thanks{Job Title, Department, Address, and AIAA Member Grade.}\\
{\normalsize\itshape
Business or Academic Affiliation, City, Province, Zipcode, Country}
}
并有一个更紧凑的命令,如下所示(下面是伪代码):
\begin{myAuthorsCode}{[Author1, Author2]}{[JobTitle1, JobTitle2]}{[Department1, Department2]}{[Address1, Address2]}{[AIAAMemberGrade1, AIAAMemberGrade2]}\end{myAuthorsCode}
我不认为 [ ] 可以这样使用,但我把它们放在那里是为了表明我正试图传递一个向量(比如 MATLAB)作为输入参数。即:
\begin{myAuthorsCode}{AuthorNames}{JobTitles}{Departments}{Addresses}{MemberGrades}
\end{myAuthorsCode}
使得“作者 1”和“作者 2”是“作者姓名”
和
“职位 1”和“职位 2”是“职称”
等等;命令将对其进行处理并将它们全部配对:
作者姓名(i)和职位(i)、部门(i)、地址(i)、和会员等级(i);
作者姓名(i+1)和职位(i+1)、部门(i+1)、地址(i+1)、和会员等级(i+1)
对于 i = 1:length(AuthorNames),其中“i”是索引变量。
那么这可能吗?如果可能的话,我想在不需要任何外部包(即基本乳胶)的情况下做到这一点。Latex 处理此类事情的能力有多强?当然它不是 MATLAB,但你能在乳胶中放入多少逻辑?
提前致谢
答案1
由于 LaTeX 本身就是一个 TeX 包,我不太明白为什么您要在不使用外部包的情况下执行此操作。我猜简短的回答是,仅使用 LaTeX 无法做到这一点,因为它没有提供您需要的工具,但如果您改用底层 TeX 引擎,则可以做到这一点。
我不知道AIAA package
and,特别是\author{...}
命令需要什么。它可能与通常的命令类似\author{...}
,但由于 MWE 对三位作者的处理略有不同,下面的代码仅显示如何拆分以逗号分隔的“作者-资料对”列表。
基本思想是使用 TeX 原始\def
命令将“作者”与“内容”分开,您可以这样做:
\def\BreakUpAuthor#1,#2!{Author: #1, Stuff: #2.}
因此,#1
和#2
用逗号分隔,并#2
在看到感叹号时结束。我们可以使用任何东西代替!
。我使用 是!
因为它很方便,而且我认为它不太可能出现在“东西”中。接下来,我们需要“循环遍历”逗号分隔的作者-东西对列表,我们可以使用递归方式执行此操作
\def\AuthorLoop#1,#2!{
\BreakAuthor#1!\if\relax#2\relax\else\AuthorLoop#2!\fi
}
因此,这将传递#1!
(作者资料对)到 ,并且\BreakAuthor
如果#2
不为“空”,则\AuthorLoop
再次使用进行调用#2!
。请注意,这会添加标记 结尾的感叹号#2
。(事实上,这并不那么健壮,如下所示,最好使用\detokenize
来清理#2
。)要使其工作,现在只需定义
\newcommand\Author[1]{\AuthorLoop#1,!}
,!
请注意,这会通过后面出现的将最后一个作者-资料对设置为“空”,#1
因为最后一个逗号和感叹号之间没有任何内容。如果我们现在使用
\Author{{Author1, Stuff1},{Author2,Stuff2}}
发生的事情是,\AuthorLoop
看到#1=Author1, Stuff1
和#2={Author2,Stuff2},
,因此它将传递#1!
给\BreakUpAuthor
,然后用调用自身#2!
。在第二次运行时,#1=Author2,Stuff2
和#2
为空,因此循环停止。在此过程中,感叹号被添加多次,但它们和逗号仅用于将参数划分为宏,因此它们在每个步骤中都会被丢弃并且永远不会被打印。
把所有这些放在一起,代码:
\documentclass{article}
\parindent=0pt% nicer looking output
\let\And\newline% default separator
\def\BreakUpAuthor#1,#2!{% Author, stuff
Author: #1, Stuff: #2.
}
\def\AuthorLoop#1,#2!{\separator\let\separator\And% use and set \separator=\and
\BreakUpAuthor#1!% break up author and stuff
\if\relax\detokenize{#2}\relax\else\AuthorLoop#2!\fi% loop if non-empty
}
\newcommand\Authors[1]{\let\separator\relax\AuthorLoop#1,!}% set separator and loop
\begin{document}
\Authors{{First Author, stuff},{Second author, more stuff},{Third author, thanks}}
\end{document}
产生输出
为了保险起见,我还添加了一个分隔符\separator
,它对第一个作者-内容对不执行任何操作,之后它变为\and
,即\newline
。
您会发现此代码存在问题,因为如果项目之间有空格,它可能会做出奇怪的事情。例如,代码在
\Authors{{First Author, stuff}, {Second author, more stuff}}
因为前面有空格{Second author, more stuff}
。所有这些问题都是可以修复的,但与其重新发明轮子,不如使用电子工具箱或者,如果你真的很热衷于探索LaTeX3。
编辑
相比之下,这里有一种方法可以使用一些包来实现这一点:
\documentclass{article}
\usepackage{xparse}% mainly for \SplitArgument
\usepackage{etoolbox}% for \forcsvlist
\parindent=0pt% nicer looking output
\let\And\newline% default separator
\NewDocumentCommand\AnAuthor{mm}{\separator\let\separator\And%
Author: #1, Stuff: #2.}
\NewDocumentCommand\BreakUpAuthor{>{\SplitArgument{1}{,}}m}{\AnAuthor #1}
\NewDocumentCommand\Authors{m}{%
\let\separator\relax% set the initial separator to nothing
\forcsvlist\BreakUpAuthor{#1}% apply \BreakUpAuthor to each pair
}
\begin{document}
\Authors{{First Author, stuff},{Second author, more stuff}, {Third author, thanks}}
\end{document}
输出与之前相同,但此宏对输入中的空格不太敏感,特别是它接受对上述代码有问题的输入。代码的长度与之前相似,但我认为它更具可读性。
答案2
这Nicola Talbot 博士的数据工具包你可能会感兴趣
您想知道可以在 LaTeX 中放入多少逻辑吗?
嗯——人们说(La)TeX 是图灵完备的。 :-)
您希望不使用任何附加软件包就能完成任务吗?
你的愿望就是我的命令。:-)
下面的示例不需要额外的包,也不需要 eTeX 扩展等。
真正的挑战是以在完全扩展的环境下也能发挥作用的方式实现事物。
即,以某种方式实现您的算法,使得在执行构成实现的宏时不会发生临时分配。;-)
我已尽最大努力给出了下面的例子。
\csname..\endcsname
只要用户传递给这些宏机制的参数适合,环境底层的宏机制甚至可以在内部使用\csname..\endcsname
;-)
用 (La)TeX 编程时采用这种方法的问题在于可能会生成难以理解的代码。;->
我在某个方面确实偏离了你的规范:
您希望维护五个列表:
- 作者姓名列表,
- 职位列表,
- 部门列表,
- 地址列表,
- 会员等级列表。
您希望这些列表是逗号列表,即列表,其中单个项目彼此之间用逗号分隔。
相反,我以这些列表的方式实现了这些事情未限定参数列表,即,单个项目嵌套在左花括号和右花括号内的列表。
我这样做是因为逗号列表需要逗号列表解析,这意味着
- 处理可能围绕逗号的空格,
- 用于屏蔽单个项目一部分的逗号的特殊方法,
- 用于掩盖应围绕单个项目的空间的特殊方法,
- 避免意外拆除牙套的预防措施,
- 等等。
这些事情都是可行的。
如果你坚持的话我可以做到。
但这将会有更多的代码。
我认为我现在所创作的东西的难以捉摸的程度已经足够了。;-)
\documentclass{article}
\makeatletter
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange
%% \UD@CheckWhetherNull,
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%=============================================================================
%% Code for \ExtractKthArg
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%
%% \UD@ExtractKthArg{<integer K>}{<list of undelimited args>}
%%
%% In case there is no K-th argument in <list of indelimited args> :
%% Does not deliver any token.
%% In case there is a K-th argument in <list of indelimited args> :
%% Does deliver that K-th argument with one level of surrounding braces removed
%% if that was present and then in any case one level of braces added.
%%
%% Examples:
%%
%% \ExtractKthArg{0}{ABCDE} yields: <nothing>
%%
%% \ExtractKthArg{3}{ABCDE} yields: {C}
%%
%% \ExtractKthArg{3}{AB{CD}E} yields: {CD}
%%
%% \ExtractKthArg{4}{{001}{002}{003}{004}{005}} yields: {004}
%%
%% \ExtractKthArg{6}{{001}{002}{003}} yields: <nothing>
%%
%% \ExtractKthArg{1}{{}{001}{002}{003}} yields: {}
%%
%%-----------------------------------------------------------------------------
\newcommand\UD@ExtractKthArg[1]{%
\romannumeral0%
% #1: <integer number K>
\expandafter\UD@ExtractKthArgCheck
\expandafter{\romannumeral\number\number#1 000}%
}%
\newcommand\UD@ExtractKthArgCheck[2]{%
\UD@CheckWhetherNull{#1}{ }{%
\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}%
}%
}%
\newcommand\UD@ExtractKthArgLoop[2]{%
\UD@CheckWhetherNull{#2}{ }{%
\UD@CheckWhetherNull{#1}{%
\UD@ExtractFirstArgLoop{#2\UD@SelDOm}%
}{%
\expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}#2}%
{\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}}%
}%
}%
}%
\newcommand\UD@RemoveTillUD@SelDOm{}%
\long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{ #1}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% Code for expandable incrementing of number without eTeX
%%=============================================================================
%% \UD@increment{<non-negative integeral number k as sequence of
%% catcode-12-character-tokens
%% from the set 0123456789>}
%% ->
%% <non-negative integeral number (k+1) as sequence of
%% catcode-12-character-tokens
%% from the set 0123456789>
%%
%% Emptiness is interpreted as "0"
%%
%% Examples:
%% \UD@increment{999} -> 1000
%% \UD@increment{0} -> 1
%% \UD@increment{} -> 1
%%
%% The result is delivered after two expansion-steps.
%%.........................................................................
\newcommand\UD@incrementrevert[3]{%
\UD@incrementinnerrevert{#1}{#2}{}#3\relax
}%
\newcommand\UD@incrementinnerrevert[4]{%
\ifx\relax#4%
\expandafter\UD@firstoftwo
\else
\expandafter\UD@secondoftwo
\fi
{#1#3#2}{\UD@incrementinnerrevert{#1}{#2}{#4#3}}%
}%
\newcommand\UD@increment[1]{%
\romannumeral0\UD@incrementrevert{\UD@incrementfork{}}{\relax}{#1}%
}%
\newcommand\UD@incrementselect{}%
\long\def\UD@incrementselect#10123456789\relax#2#3!!{#2}%
\newcommand\UD@incrementfork[2]{%
\UD@incrementselect
#2123456789\relax{\UD@incrementinnerrevert{ }{}{}#11}%
0#223456789\relax{\UD@incrementinnerrevert{ }{}{}#12}%
01#23456789\relax{\UD@incrementinnerrevert{ }{}{}#13}%
012#2456789\relax{\UD@incrementinnerrevert{ }{}{}#14}%
0123#256789\relax{\UD@incrementinnerrevert{ }{}{}#15}%
01234#26789\relax{\UD@incrementinnerrevert{ }{}{}#16}%
012345#2789\relax{\UD@incrementinnerrevert{ }{}{}#17}%
0123456#289\relax{\UD@incrementinnerrevert{ }{}{}#18}%
01234567#29\relax{\UD@incrementinnerrevert{ }{}{}#19}%
012345678#2\relax{\UD@incrementfork{#10}}%
0123456789#2{\UD@incrementinnerrevert{ }{}{}#11\relax}%
0123456789\relax{\UD@incrementinnerrevert{ }{}{}#11}%
!!%
}%
%%=============================================================================
%%Code for turning name of data-field into number of undelimited macro-argument
%% Possible data-field-names are:
%% AuthorNames -> 1
%% JobTitles - > 2
%% Departments -> 3
%% Addresses -> 4
%% MemberGrades-> 5
%%=============================================================================
\newcommand\@gobbletoexclam{}\long\def\@gobbletoexclam#1!{}
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\@gobbletoexclam#1!}%
}%
\newcommand\UD@DataFieldToNumber[1]{%
\romannumeral0%
\UD@CheckWhetherNoExclam{#1}{%
\UD@DataFieldFork!#1!JobTitles!Departments!Addresses!MemberGrades!{ 1}%
!AuthorNames!#1!Departments!Addresses!MemberGrades!{ 2}%
!AuthorNames!JobTitles!#1!Addresses!MemberGrades!{ 3}%
!AuthorNames!JobTitles!Departments!#1!MemberGrades!{ 4}%
!AuthorNames!JobTitles!Departments!Addresses!#1!{ 5}%
!AuthorNames!JobTitles!Departments!Addresses!MemberGrades!{ 0}%
!!!!%
}{ 0}%
}%
\newcommand\UD@DataFieldFork{}%
\long\def\UD@DataFieldFork
#1!AuthorNames!JobTitles!Departments!Addresses!MemberGrades!#2#3!!!!{#2}%
%%=============================================================================
%% Code for returning data of datafield-index.
%%
%% \ReturnDataFieldOfIndex{<datalist macro>}%
%% {<name of datafield>}%
%% {<index-number>}%
%%
%% Example:
%% \ReturnDataFieldOfIndex{\mymacro}{JobTitles}{3}
%% returns the third JobTitle if existing.
%%
%% Actually the phrase "JobTitles" gets transformed to the number 2, thus
%% this returns the third argument that is nested within the second argument
%% of the expansion of \mymacro.
%% In case an argument is returned, it will always be nested in curly
%% braces!
%%
%% Returns nothing/emptiness/not even curly braces in case the
%% datafield does not exist.
%%=============================================================================
\newcommand\ReturnDataFieldOfIndex[2]{%
\romannumeral0%
\expandafter\InternalReturnDataFieldOfIndex
\expandafter{#1}{\UD@DataFieldToNumber{#2}}%
}%
%%-----------------------------------------------------------------------------
%% \romannumeral0\InternalReturnDataFieldOfIndex{<datalist>}%
%% {<number of datafield>}%
%% {<index-number>}%
%% (Here the <datalist-macro> is already expanded.)
\newcommand\InternalReturnDataFieldOfIndex[3]{%
\expandafter\expandafter\expandafter\UD@CheckWhetherNull
\expandafter\expandafter\expandafter{%
\UD@ExtractKthArg{#2}{#1}%
}{ }{%
\expandafter\expandafter\expandafter\UD@PassFirstToSecond
\UD@ExtractKthArg{#2}{#1}%
{%
\UD@firstoftwo{\expandafter\expandafter\expandafter}{} %
\UD@ExtractKthArg{#3}%
}%
}%
}%
%%=============================================================================
%% Code for returning data of all datafields with same index.
%%
%% \ReturnAllDataFieldsOfIndex{<datalist macro>}{<index>}{<action to apply>}%
%%
%% Extracts from each argument of the expansion of <datalist macro> the
%% <index>-th argument nested inside that argument.
%%
%% Prepends to the result the tokens that form <action to apply>
%%
%%=============================================================================
\newcommand\ReturnAllDataFieldsOfIndex[3]{%
\romannumeral0\expandafter\InternalReturnAllDataFieldsOfIndex
\expandafter{\expandafter}%
\expandafter{\expandafter1\expandafter}%
\expandafter{#1}{#2}{#3}%
}%
\newcommand\InternalReturnAllDataFieldsOfIndex[5]{%
% #1 - <DataFieldsCollectedSoFar>
% #2 - <number of data-field>
% #3 - <datalist>
% #4 - <index>
% #5 - <action to apply>
\expandafter\expandafter\expandafter\UD@CheckWhetherNull
\expandafter\expandafter\expandafter{%
\UD@ExtractKthArg{#2}{#3}%
}{\UD@CheckWhetherNull{#1}{ }{ #5#1}}{%
\expandafter\expandafter\expandafter\UD@PassFirstToSecond
\expandafter\expandafter\expandafter{\UD@increment{#2}}%
{%
\expandafter\expandafter\expandafter\InternalReturnAllDataFieldsOfIndex
\expandafter\expandafter\expandafter{%
\expandafter\UD@Exchange\expandafter{%
\romannumeral0\InternalReturnDataFieldOfIndex{#3}{#2}{#4}}{#1}}%
}%
{#3}{#4}{#5}%
}%
}%
%%=============================================================================
%% Code for returning with each index data of all datafields with same index.
%%
%% \ReturnAllDataFieldsOfEachIndex{<datalist macro>}%
%% {<separator>}%
%% {<action to apply>}%
%%
%% With each possible <index>-value extracts from each argument of the
%% expansion of <datalist macro> the <index>-th argument nested inside
%% that argument.
%% With each possible <index>-value prepends <action to apply> and in case
%% <index>-value > 1, also prepends <separator>.
%%=============================================================================
\newcommand\ReturnAllDataFieldsOfEachIndex[3]{%
\romannumeral0\expandafter\InternalReturnAllDataFieldsOfEachIndex
\expandafter{\expandafter}\expandafter{\expandafter1%
\expandafter}\expandafter{#1}{#2}{#3}{}%
}%
\newcommand\InternalReturnAllDataFieldsOfEachIndex[6]{%
% #1 - <data-rows collected so far>
% #2 - <current index number>%
% #3 - <data-list>
% #4 - <separator>
% #5 - <action to apply>
% #6 - <separator in this iteration>
\expandafter\UD@CheckWhetherNull
\expandafter{\romannumeral0\InternalReturnAllDataFieldsOfIndex{}{1}{#3}{#2}{}}{ #1}{%
\expandafter\expandafter\expandafter\UD@PassFirstToSecond
\expandafter\expandafter\expandafter{\UD@increment{#2}}{%
\expandafter\expandafter\expandafter\InternalReturnAllDataFieldsOfEachIndex
\expandafter\expandafter\expandafter{%
\expandafter\UD@Exchange
\expandafter{\romannumeral0\InternalReturnAllDataFieldsOfIndex{}{1}{#3}{#2}{#5}}%
{#1#6}%
}%
}%
{#3}{#4}{#5}{#4}%
}%
}%
%%=============================================================================
%% Code for building up the myAuthorsCode-environment:
%%=============================================================================
\newcommand\@authorlist{}%
\newenvironment{myAuthorsCode}[5]{%
\renewcommand\@authorlist{{#1}{#2}{#3}{#4}{#5}}%
\global\let\@authorlist\@authorlist
\author{%
\ReturnAllDataFieldsOfEachIndex{\@authorlist}{\and}{\@PrintAuthor}%
}%
}{}%
\newcommand\@PrintAuthor[5]{%
#1\UD@CheckWhetherNull{#2#3#4#5}{}{%
\thanks{%
#2%
\UD@CheckWhetherNull{#3}{}{\UD@CheckWhetherNull{#2}{}{, }}#3%
\UD@CheckWhetherNull{#4}{}{\UD@CheckWhetherNull{#2#3}{}{, }}#4%
\UD@CheckWhetherNull{#5}{}{\UD@CheckWhetherNull{#2#3#4}{}{ and }}#5%
}%
}%
}%
\makeatother
\pagestyle{empty}
\title{My work}
\begin{myAuthorsCode}%
%% Datafield AuthorNames:
{{Author A}{Author B}{Author C}{Author D}{Author E}}%
%% Datafield JobTitles:
{{JobTitle A}{JobTitle B}{JobTitle C}{JobTitle D}{JobTitle E}}%
%% Datafield Departments:
{{Department A}{Department B}{Department C}{Department D}{Department E}}%
%% Datafield Addresses:
{{Address A}{Address B}{Address C}{Address D}{Address E}}%
%% Datafield MemberGrades:
{{MemberGrade A}{MemberGrade B}{MemberGrade C}{MemberGrade D}{MemberGrade E}}%
\end{myAuthorsCode}
\parindent=0pt
\begin{document}
\maketitle\thispagestyle{empty}
\newpage
% Now testing the macros underlying the myAuthorsCode-environment:
\newcommand\PrintAllDataFieldsOfIndex[5]{%
\textbf{Author-Name:} #1;\\
\textbf{Job-Title:} #2;\\
\textbf{Department:} #3;\\
\textbf{Address:} #4;\\
\textbf{Member Grade:} #5.%
}%
\newcommand\AuthorlistForTests{%
%% Datafield AuthorNames:
{{author 1}{author 2}{author 3}{author 4}{author 5}}%
%% Datafield JobTitles:
{{jobtitle 1}{jobtitle 2}{jobtitle 3}{jobtitle 4}{jobtitle 5}}%
%% Datafield Departments:
{{department 1}{department 2}{department 3}{department 4}{department 5}}%
%% Datafield Addresses:
{{address 1}{address 2}{address 3}{address 4}{address 5}}%
%% Datafield MemberGrades:
{{membergrade 1}{membergrade 2}{membergrade 3}{membergrade 4}{membergrade 5}}%
}%
\begin{verbatim}
\newcommand\PrintAllDataFieldsOfIndex[5]{%
\textbf{Author-Name:} #1;\\
\textbf{Job-Title:} #2;\\
\textbf{Department:} #3;\\
\textbf{Address:} #4;\\
\textbf{Member Grade:} #5.%
}%
\newcommand\AuthorlistForTests{%
%% Datafield AuthorNames:
{{author 1}{author 2}{author 3}{author 4}{author 5}}%
%% Datafield JobTitles:
{{jobtitle 1}{jobtitle 2}{jobtitle 3}{jobtitle 4}{jobtitle 5}}%
%% Datafield Departments:
{{department 1}{department 2}{department 3}{department 4}{department 5}}%
%% Datafield Addresses:
{{address 1}{address 2}{address 3}{address 4}{address 5}}%
%% Datafield MemberGrades:
{{membergrade 1}{membergrade 2}{membergrade 3}{membergrade 4}{membergrade 5}}%
}%
\end{verbatim}
\hrulefill\vfill
\verb|\ReturnDataFieldOfIndex{\AuthorlistForTests}{Departments}{3}|%
\\\null\\\quad yields:\\\null\\%
\ReturnDataFieldOfIndex{\AuthorlistForTests}{Departments}{3}
\vfill
\verb|\ReturnDataFieldOfIndex{\AuthorlistForTests}{JobTitles}{2}|%
\\\null\\\quad yields:\\\null\\%
\ReturnDataFieldOfIndex{\AuthorlistForTests}{JobTitles}{2}%
\vfill
(Possible datafield-names are:\\
\verb|AuthorNames|, \verb|JobTitles|, \verb|Departments|,
\verb|Addresses|, \verb|MemberGrades|.)
\vfill\hrulefill\vfill
\verb|\ReturnAllDataFieldsOfIndex{\AuthorlistForTests}{4}{\PrintAllDataFieldsOfIndex}|%
\\\null\\\quad yields:\\\null\\%
\ReturnAllDataFieldsOfIndex{\AuthorlistForTests}{4}{\PrintAllDataFieldsOfIndex}
\newpage
\verb|\ReturnAllDataFieldsOfEachIndex{\AuthorlistForTests}%|\\
\verb| {\\\null\dotfill\\}%|\\
\verb| {\PrintAllDataFieldsOfIndex}|%
\\\null\\\quad yields:\\\null\\%
\ReturnAllDataFieldsOfEachIndex{\AuthorlistForTests}%
{\\\null\dotfill\\}%
{\PrintAllDataFieldsOfIndex}
\end{document}