New command with two values, one of them only mentioned in the first time

You can use a pair of commands one of which redefines itself:

\makeatletter
\newcommand*\einstein{Albert Einstein\death@einstein}
\def\death@einstein{ ($\dagger$~1955/04/18)\def\death@einstein{}}
\makeatother

Then every time you use \einstein it will print the name Albert Einstein immediatly followed by the call of \death@einstein. The latter will then print ($\dagger$~1955/04/18) and then define itself to to nothing the next time it is used.

\documentclass{article}

\makeatletter
\newcommand*\einstein{Albert Einstein\death@einstein}
\def\death@einstein{ ($\dagger$~1955/04/18)\def\death@einstein{}}
\makeatother

\begin{document}

\einstein \par
\einstein

\end{document}

enter image description here

This can be automated if you need it more than once or twice:

\documentclass{article}

\makeatletter
\newcommand*\newperson[3]{%
  \def#1{#2\csname death@#2\endcsname}%
  \@namedef{death@#2}{ ($\dagger$~#3)\@namedef{death@#2}{}}%
}
\makeatother

\newperson\einstein{Albert Einstein}{1955/04/18}
\newperson\planck{Max Planck}{1947/10/04}

\begin{document}

\einstein \par
\einstein

\planck \par
\planck

\end{document}

enter image description here


Alternative version with a boolean check:

\documentclass{article}
\usepackage{xspace}
\newif\ifauthordisplayed         % create boolean
\authordisplayedfalse            % set to false
\def\am{%
\ifauthordisplayed%              % if boolean true
Ali Mabrook\xspace%              % print only the name
\else
Ali Mabrook (died 2016)\xspace%  % print name and date
\authordisplayedtrue%            % and set boolean to true
\fi%
}
\begin{document}
\am was an author. His name is \am.
\end{document}

The \xspace macro from the package with the same name inserts a space after a word except when it is followed by punctuation, footnote marks etc. This is useful because the original space is removed by the macro processing procedure when the macro is called in the document.

Result:

enter image description here

This can be generalized for more than one author using the xkeyval package. To make this solution work there are some commands that need to be constructed with \csname, for example a boolean for a key contained in the argument #1 can be constructed using \expandafter\newif\csname if#1displayed\endcsname, and similar for reading the values of the keys from the \KV@ macros created by \define@key. Admittedly this is not very easy to read but hopefully the steps are clear.

MWE:

\documentclass{article}
\usepackage{xkeyval}
\usepackage{xspace}
\makeatletter
\newcommand{\addauthor}[3]{%
% create boolean for the key in argument #1
\expandafter\newif\csname if#1displayed\endcsname
% set boolean to false
\csname #1displayedfalse\endcsname
% define function for this key
\define@key{myauthors}{#1}{%
% if displayed before
\csname if#1displayed\endcsname
% print just the name
#2%
\else%
% print full info and set boolean to true
#2 (died #3)%
\csname #1displayedtrue\endcsname
\fi%
}
}

% call command that is created by define@key
\newcommand{\displayauthor}[1]{%
\csname KV@myauthors@#1\endcsname{}\xspace%
}
\makeatother

\begin{document}
\addauthor{am}{Ali Mabrook}{2016}
\addauthor{js}{John Smith}{2004}

\displayauthor{am} was an author. His name was \displayauthor{am}.

\displayauthor{js} was an author. His name was \displayauthor{js}.

\end{document}

Result:

enter image description here

Tags:

Macros