\newcommand: Использование одного параметра в качестве параметра по умолчанию для другого

\newcommand: Использование одного параметра в качестве параметра по умолчанию для другого

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

К сожалению,

\newcommand{\mycommand}[2][#1]{ ... }

не работает, также не работает

\newcommand{\mycommand}[2][#2]{ ... }

Кто-нибудь знает, как это сделать?

решение1

Хорошие новости: вы можете сделать это очень легко с помощью xparse:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\foo}{O{#2}m}{%
  Optional=``#1'', mandatory=``#2''\par
}
\NewDocumentCommand{\oof}{mO{#1}}{%
  Mandatory=``#1'', optional=``#2''\par
}

\begin{document}

\foo{x}

\foo[y]{x}

\oof{x}

\oof{x}[y]

\end{document}

Спецификатор аргумента O{...}принимает в качестве аргумента то, что следует заменить по умолчанию, когда сам аргумент не появляется во время вызова. Это может быть токен параметра, ссылающийся на другой аргумент.

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

решение2

Вы можете использоватьxparseлегко обусловить, присутствовал ли необязательный аргумент или нет, и предоставить соответствующую комбинацию другой (вспомогательной) функции. Вот пример:

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

\documentclass{article}

\usepackage{xparse}

\newcommand{\printthis}[2]{%
  Optional: #1; Mandatory: #2%
}

\NewDocumentCommand{\mycommand}{o m}{%
  \IfValueTF{#1}
    {\printthis{#1}{#2}}% \mycommand[..]{...}
    {\printthis{#2}{#2}}% \mycommand{...}
}

\begin{document}

\mycommand{first}

\mycommand[first]{second}

\end{document}

Немного иная версия этого вытекает из использования \caption, где вы можете указать необязательный аргумент для LoT/LoF, но если вы этого не сделаете, вместо этого будут отправлены обязательные аргументы (аналогично для секционных единиц с необязательными аргументами, предназначенными для ToC). Здесь используетсяядро's \@dblarg:

\documentclass{article}

\newcommand{\printthis}[2][]{%
  Optional: #1; Mandatory: #2%
}

\makeatletter
\newcommand{\mycommand}{%
  \@dblarg\printthis
}
\makeatother

\begin{document}

\mycommand{first}

\mycommand[first]{second}

\end{document}

решение3

Это попытка добавить защиту, как и в случае с другими макросами, обрабатывающими необязательные аргументы:

%%\errorcontextlines=1000
\documentclass[a4paper]{article}

\makeatletter
\newcommand\makefirstmandatorytheoptional[1]{%
  \expandafter\innermakefirstmandatorytheoptional
  \expandafter{\csname\string#1\endcsname}{#1}%
}%
\newcommand\innermakefirstmandatorytheoptional[2]{%
  \def#2{%
    \ifx\protect\@typeset@protect
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    {\kernel@ifnextchar[{#1}{\@dblarg{#1}}}%
    {\protect#2}%
  }%
}%
\newcommand\mycommand[2][dummyoptional]{%
  This is taken for the optional argument: #1.\\
  This is taken for the mandatory argument: #2.
}%
\makefirstmandatorytheoptional{\mycommand}%
\makeatother

\parindent=0ex
\parskip=\medskipamount

\begin{document}

No optional argument given---\verb|\mycommand{A}|:

\mycommand{A}

Optional argument "B" given---\verb|\mycommand[B]{A}|:

\mycommand[B]{A}

\end{document}

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

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