# How to create a new cite function with unknown amount of input arguments?

I'm currently working on my master thesis, and my supervisor has requested that citations at the end of paragraphs looks as following: (Author1, Year1, Author2, Year2, AuthorN, YearN)

Since I'm new at LaTeX I've so far just manually created different new commands for this, depending on amount of input authors, as follows:

\newcommand\citepara[1]{(\citeauthor{#1}, \citeyear{#1})}
\newcommand\citeparatwo[2]{(\citeauthor{#1}, \citeyear{#1},\citeauthor{#2}, \citeyear{#2})}
\newcommand\citeparathree[3]{(\citeauthor{#1}, \citeyear{#1},\citeauthor{#2}, \citeyear{#2},\citeauthor{#3}, \citeyear{#3})}


(and naturally could go on doing this)

I however hope there is a way to solve this so that the same command can take several input arguments, and still output in the above mentioned format. If more than one input argument is given to \citepara it is printed (Author1, Author2, Year1, Year2) right now which is not acceptable.

The documentclass is a local university version - but it is based on the memoir class.

Here is a general loop command executing the loop body repeatedly for a list of items.

% \applyto{..loop body..}{..list of items..}
\newcommand\applyto[2]{\def\doxloop{#1}\expandafter\xloop#2\relax}
\newcommand\xloop[1]{\ifx\relax#1\else\doxloop{#1}\expandafter\xloop\fi}


In your case the loop body consists of two commands. The first one, \inter, generates a comma between any two references, and the second one, \citepara, gets one item as an argument and is responsible for typesetting the reference. The command \citeparas executes the loop; it is the one that is finally used.

\newcommand\citepara[1]{\citeauthor{#1}, \citeyear{#1}}
\newcommand\inter{}
\newcommand\citeparas[1]%
{\def\inter{\def\inter{, }}%
(\applyto{\inter\citepara}{#1})%
}


Examples of usage:

\citeparas{{einstein}}
\citeparas{{einstein}{latexcompanion}}
\citeparas{{einstein}{latexcompanion}{knuthwebsite}}


\begin{filecontents}{test.bib}
@article{einstein,
author =       "Albert Einstein",
title =        "{Zur Elektrodynamik bewegter K{\"o}rper}. ({German})
[{On} the electrodynamics of moving bodies]",
journal =      "Annalen der Physik",
volume =       "322",
number =       "10",
pages =        "891--921",
year =         "1905",
DOI =          "http://dx.doi.org/10.1002/andp.19053221004"
}

@book{latexcompanion,
author    = "Michel Goossens and Frank Mittelbach and Alexander Samarin",
title     = "The \LaTeX\ Companion",
year      = "1993",
}

@misc{knuthwebsite,
author    = "Donald Knuth",
title     = "Knuth: Computers and Typesetting",
url       = "http://www-cs-faculty.stanford.edu/\~{}uno/abcde.html",
year      = "2017"
}
\end{filecontents}
\documentclass{article}
\usepackage{natbib}
\bibliographystyle{abbrvnat}

% \applyto{..loop body..}{..list of items..}
\newcommand\applyto[2]{\def\doxloop{#1}\expandafter\xloop#2\relax}
\newcommand\xloop[1]{\ifx\relax#1\else\doxloop{#1}\expandafter\xloop\fi}

\newcommand\citepara[1]{\citeauthor{#1}, \citeyear{#1}}
\newcommand\inter{}
\newcommand\citeparas[1]%
{\def\inter{\def\inter{, }}%
(\applyto{\inter\citepara}{#1})%
}

\begin{document}
\citeparas{{einstein}}

\citeparas{{einstein}{latexcompanion}}

\citeparas{{einstein}{latexcompanion}{knuthwebsite}}

\bibliography{test}
\end{document}


Another solution providing a slightly faster input:

\documentclass[]{memoir}

\makeatletter
\newcommand{\@@citepara}[1]{\citeauthor{#1}, \citeyear{#1}}
\newcommand{\@citepara}{}
\def\@citepara|#1,#2|{%
\ifx&#1&%
\else\expandafter\@@citepara{#1}\fi%
\ifx&#2&%
\else, \expandafter\@citepara|#2|\fi%
}
\newcommand{\citepara}[1]{(\@citepara|#1,|)}
\makeatother

\begin{document}
\noindent
\citepara{1}\\
\citepara{1,2}\\
\citepara{1,2,3}\\
\citepara{1,2,3,4}\\
\citepara{1,2,3,4,5}\\
\citepara{1,2,3,4,5,6}\\
\citepara{1,2,3,4,5,6,7}\\
\citepara{1,2,3,4,5,6,7,8}\\
\citepara{1,2,3,4,5,6,7,8,9}\\
\end{document}



• Looks like an interesting but tricky solution. I don't quite understand what \ifx compares to what. E.g., \citepara{aa} and \citepara{aa,bb} don't seem to work. – gernot Mar 23 '17 at 18:32
• @gernot The \ifx with nothing else returns true for empty arguments. The aa or bb don't work, because \ifx returns true because it detects that a=a and b=b. Thank you for your comment. I've made an edit, now two identical letters are no problem anymore. To be honest, I don't understand your answer as well. – Skillmon Mar 23 '17 at 19:06