\newcommand: Usando um parâmetro como padrão para o outro

\newcommand: Usando um parâmetro como padrão para o outro

Gostaria de definir uma macro que receba dois argumentos, um dos quais é opcional. Se não for fornecido, deverá considerar o outro como valor padrão.

Infelizmente,

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

não funciona, nem

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

Alguém sabe como fazer isto?

Responder1

Boas notícias: você pode fazer isso facilmente com 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 especificador de argumento O{...}toma como argumento o que substituir como padrão quando o argumento em si não aparece no momento da chamada. Este pode muito bem ser um token de parâmetro referente a outro argumento.

insira a descrição da imagem aqui

Responder2

Você pode usarxparsepara condicionar facilmente se um argumento opcional estava presente ou não e fornecer a combinação apropriada para outra função (auxiliar). Aqui está um exemplo:

insira a descrição da imagem aqui

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

Uma versão ligeiramente diferente disso decorre do uso de \caption, onde você pode fornecer um argumento opcional para o LoT/LoF, mas se não o fizer, os argumentos obrigatórios serão enviados (da mesma forma para unidades seccionais com argumentos opcionais destinados ao ToC ). Isso usa onúcleoé \@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}

Responder3

Esta é uma tentativa de adicionar proteção como acontece com outras macros que processam argumentos opcionais:

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

insira a descrição da imagem aqui

informação relacionada