Новая команда с двумя значениями, одно из которых упоминается только в первый раз

Новая команда с двумя значениями, одно из которых упоминается только в первый раз

Я хотел бы определить новую команду, которая имеет два значения, одно из которых — имя автора, а другое — дата его смерти, при этом второе значение упоминается только при первом использовании команды, а затем упоминается только имя автора. Как это сделать?

решение1

Вы можете использовать пару команд, одна из которых переопределяет сама себя:

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

Тогда каждый раз, когда вы используете \einsteinего, он будет печатать имя, Albert Einsteinза которым сразу же последует вызов \death@einstein. Последний затем напечатает ($\dagger$~1955/04/18)и определитсамчтобы свести его к нулю при следующем использовании.

\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}

введите описание изображения здесь

Если вам это нужно чаще одного или двух раз, это можно автоматизировать:

\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}

введите описание изображения здесь

решение2

Альтернативная версия с булевой проверкой:

\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}

Макрос \xspaceиз пакета с таким же именем вставляет пробел после слова, за исключением случаев, когда за ним следуют знаки препинания, сноски и т. д. Это полезно, поскольку исходный пробел удаляется процедурой обработки макроса при вызове макроса в документе.

Результат:

введите описание изображения здесь

Это можно обобщить для более чем одного автора, использующего xkeyvalпакет. Чтобы это решение работало, есть некоторые команды, которые нужно построить с помощью \csname, например, логическое значение для ключа, содержащегося в аргументе, #1можно построить с помощью \expandafter\newif\csname if#1displayed\endcsname, и аналогично для чтения значений ключей из макросов, \KV@созданных с помощью \define@key. По общему признанию, это не очень легко читать, но, надеюсь, шаги понятны.

МВЭ:

\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}

Результат:

введите описание изображения здесь

Связанный контент