I now see from your other questions that, despite your comments concerning how easy it is to do this in modern programming languages, you are determined to compare those languages with TeX, rejecting the modern interfaces which build upon it. Little wonder, then, that the TeX case seems more difficult. For a fair comparison, you need to compare other languages available at the time TeX was created or, at least, finalised. Perhaps other languages available in the early 80s did make this easy - I wouldn't know. But comparing it with today's Python and C is comparing apples and oranges i.e. by no means fair!
Here's an implementation using a modern interface which requires no tricks and relatively few lines of code. Admittedly, the names of macros etc. are longer than those used by TeX but the pay-off is code which is much more transparent and readable.
Nor do I recommend macros like \Aa
as an end user interface. They make your question significantly harder to understand and will make the commands significantly harder to use. This is true even if you are the only end user. Perhaps even especially in that case, since, if you are like me, you don't write documentation for code intended only for private use.
In any case, we can use fewer lines by far of code because we do not need to reinvent perfectly good wheels.
Here, \addauthor{}
adds an author; \authorout
finishes an author group; and \printout
prints out the entire list. Since I've basically no idea what you're trying to do, the facilities provided are likely not ideal for your purposes, but they should give you the basic idea.
Two comma separated lists are defined. One holds the current author group. The other holds the overall list of author groups. We don't need to count anything because when we use the comma list, we can tell TeX which separators should be used between items in a 2-item list, the final 2 items in a 3+-item list and the remaining pairs of items in a 3+-item list. We also have the facilities required to clear the lists as necessary. Here, I assume that the complete list should be cleared after typesetting.
Note that full expansion is activated simply by using the appropriate signature when calling the macro to use the comma list holding the current author group.
\clist_put_right:Nx \l_mapo_authors_clist { ( \clist_use:Nnnn \l_mapo_author_clist { ~and~ } { ,~ } { ~and~ } ) }
is used to add the contents of the completed author group to the main list of author groups. The :Nx
indicates that the second argument should be fully expanded, ensuring that we get the content of the list added to the main list before clearing it in the next line in readiness for the next author group.
In contrast
\clist_put_right:Nn \l_mapo_author_clist { #1 }
has the signature :Nn
which indicates the second argument should not be treated specially, as that is not required here.
Hence, there is no need to worry about how many \expandafter
s to use or where to put them.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \l_mapo_author_clist
\clist_new:N \l_mapo_authors_clist
\tl_new:N \l_mapo_end_tl
\tl_set:Nn \l_mapo_end_tl {}
\NewDocumentCommand \addauthor { m }{
\clist_put_right:Nn \l_mapo_author_clist { #1 }
}
\NewDocumentCommand \authorout {}{
\clist_put_right:Nx \l_mapo_authors_clist { ( \clist_use:Nnnn \l_mapo_author_clist { ~and~ } { ,~ } { ~and~ } ) }
\clist_clear:N \l_mapo_author_clist
}
\NewDocumentCommand \printout {}{
\clist_use:Nnnn \l_mapo_authors_clist { ~, } { ,~ } { ,~ }
\l_mapo_end_tl
\clist_clear:N \l_mapo_authors_clist
}
\ExplSyntaxOff
\begin{document}
\addauthor{a}
\addauthor{b}
\addauthor{c}
\authorout
\addauthor{d}
\authorout
\addauthor{pippo}
\addauthor{pluto}
\authorout
\addauthor{paperino}
\authorout
\printout
\end{document}
EDIT
To answer the question in comments, the aim is to modify the above code to produce the following output:
To do this, I would modify the addition of each author rather than the addition of each author group to the overall list. To do this, we can simply test whether the comma list holding the current author group is empty when we add an author. If it is empty, then we prefix the addition to the list with the required label. If not, then we simply add the new addition as usual.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \l_mapo_author_clist
\clist_new:N \l_mapo_authors_clist
\tl_new:N \l_mapo_end_tl
\tl_set:Nn \l_mapo_end_tl {}
\NewDocumentCommand \addauthor { m }{
\clist_if_empty:NTF \l_mapo_author_clist
{
\clist_put_right:Nn \l_mapo_author_clist { \textsc{Authors:~} \textit{#1} }
}
{
\clist_put_right:Nn \l_mapo_author_clist { \textit{#1} }
}
}
\NewDocumentCommand \authorout {}{
\clist_put_right:Nx \l_mapo_authors_clist { \clist_use:Nnnn \l_mapo_author_clist { ~and~ } { ,~ } { ~and~ } }
\clist_clear:N \l_mapo_author_clist
}
\NewDocumentCommand \printout {}{
\clist_use:Nnnn \l_mapo_authors_clist { ~, } { ,~ } { ,~ }
\l_mapo_end_tl
\clist_clear:N \l_mapo_authors_clist
}
\ExplSyntaxOff
\begin{document}
\addauthor{a}
\addauthor{b}
\addauthor{c}
\authorout
\addauthor{d}
\authorout
\addauthor{pippo}
\addauthor{pluto}
\authorout
\addauthor{paperino}
\authorout
\printout
\end{document}
Note that to get the space between Authors:
and the name of the author, we need ~
rather than
because
is ignored whenever expl3 syntax is active. (This is why it is not necessary to avoid spaces we don't want or to comment line endings to avoid spurious spaces as we would normally have to do. The downside is that all spaces we do want must be explicitly coded. In this context ~
is a breakable space - not an unbreakable one - as can be seen from the output of the final author group above.