Ist es in Ordnung, wenn ein Befehl mehr Argumente aufnimmt, als ihm übergeben werden?

Ist es in Ordnung, wenn ein Befehl mehr Argumente aufnimmt, als ihm übergeben werden?

Ist es in Ordnung, wenn eine Steuersequenz \fooeine andere Steuersequenz enthält \slurp, die mehr Argumente aufnimmt, als \fooihr tatsächlich übergeben werden?

Ist es beispielsweise in Ordnung, Folgendes zu tun:

\documentclass{article}

\newcommand\foo  [1]{#1 \slurp}    
\newcommand\slurp[3]{#1 #2 #3}

\begin{document}
\foo{a}{b}{c}{d}
\end{document}

An Stelle von?

\documentclass{article}

\newcommand\foo  [4]{#1 \slurp{#2}{#3}{#4}}    
\newcommand\slurp[3]{#1 #2 #3}

\begin{document}
\foo{a}{b}{c}{d}
\end{document}

Antwort1

Ist das in Ordnung? Ja, tatsächlich! Tatsächlich gibt es eine Fülle von Verwendungsmöglichkeiten für solche Makrodefinitionen. Vor allem die grundlegenden Definitionen für mit Sternchen versehene Varianten von Befehlen. Zum Beispiel:articledefiniert \sectionals

\newcommand\section{\@startsection {section}{1}{\z@}%
                                   {-3.5ex \@plus -1ex \@minus -.2ex}%
                                   {2.3ex \@plus.2ex}%
                                   {\normalfont\Large\bfseries}}

Sehen Sie, wie es dauertnullArgumente, obwohl wir es normalerweise als \section[<toc>]{<title>}?! angeben/verwenden. Das liegt daran, dass \@startsection6 Argumente benötigt werden und dann ein Test durchgeführt wird, um festzustellen, ob der Benutzer einen Stern hinzugefügt hat oder nicht. Vonlatex.ltx:

\def\@startsection#1#2#3#4#5#6{%
  \if@noskipsec \leavevmode \fi
  \par
  \@tempskipa #4\relax
  \@afterindenttrue
  \ifdim \@tempskipa <\z@
    \@tempskipa -\@tempskipa \@afterindentfalse
  \fi
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty\addvspace\@tempskipa
  \fi
  \@ifstar
    {\@ssect{#3}{#4}{#5}{#6}}%
    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}

Daher \sectionwerden die Argumente, die wir normalerweise angeben, erst zwei Schritte später von einem Makro verschlungen.

Ein weiteres gutes Beispiel dafür, warum dies eine gute Vorgehensweise ist, betrifft Änderungen an Kategoriecodes. Sobald Argumente zur Verwendung verbraucht sind, können ihre Kategoriecodes nicht mehr geändert werden. Daher wird normalerweise ein Hilfsmakro verwendet, um die Kategoriecodes zu ändern.Voralle Argumente verschlingen.

Es gibt zahlreiche weitere Beispiele in derLaTeX-Kernel, von grundlegenden Schriftartmakros über den Umgang mit dem Inhaltsverzeichnis bis hin zur Definition eines neuen Befehls über \newcommand:

\def\newcommand{\@star@or@long\new@command}

Auch hier handelt es sich um ein Makro, das keine Argumente akzeptiert, aber eine Operation ausführt, bevor es die Fackel an ein anderes Makro weitergibt. Im Allgemeinen wird dieses Prinzip im gesamten Kernel und in den Paketen häufig verwendet.

Antwort2

Wie in Werners Antwort erläutert, ist dies gängige Praxis. Alle Makros mit einer *-Variante werden folgendermaßen definiert:

\newcommand{\foo}{\@ifstar{\@sfoo}{\@foo}}
\newcommand{\@sfoo}[1]{Foo with * applied to #1}
\newcommand{\@sfoo}[1]{Foo without * applied to #1}

oder Varianten davon. Ebenso müssen Makros mit mehr als einem optionalen Argument, wie z. B. , \makeboxeinen langen Weg zurücklegen, um zu entscheiden, ob es kein, ein oder zwei optionale Argumente gibt:

\newcommand{\bar}{\@ifnextchar[{\@bar@i}{\@bar}}
\def\@bar@i[#1]{\@ifnextchar[{\@bar@ii{#1}}{\@bar@iii{#1}}
\def\@bar@ii#1[#2]#3{Bar has two optional arguments, #1 and #2, and #3}
\def\@bar@iii#1#2{Bar has one optional argument, #1, and #2}
\def\@bar#1{Bar has no optional argument and #1}

Bei xparseist die Situation ganz anders: da *-Varianten und optionale Argumente relativ allgemein angegeben werden können, ist es vorzuziehen,alleeigentliche Argumente:

\usepackage{xparse}
\NewDocumentCommand{\foo}{sm}{%
  \IfBooleanTF{#1}
    {Foo with * applied to #2}
    {Foo without * applied to #2}%
}

\NewDocumentCommand{\bar}{oom}{%
  \IfNoValueTF{#1}
    {Bar has no optional argument and #3}
    {\IfNoValueTF{#2}
       {Bar has one optional argument, #1, and #3}
       {Bar has two optional arguments, #1 and #2, and #3}%
    }%
  }%
}

Dies ist „die Zukunft“ mit LaTeX3.

verwandte Informationen