
制御シーケンスに、実際に渡される引数よりも多くの引数を吸い取る\foo
別の制御シーケンスを含めても大丈夫ですか?\slurp
\foo
たとえば、次のようにしても大丈夫でしょうか:
\documentclass{article}
\newcommand\foo [1]{#1 \slurp}
\newcommand\slurp[3]{#1 #2 #3}
\begin{document}
\foo{a}{b}{c}{d}
\end{document}
これの代わりに?
\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}
答え1
これは大丈夫でしょうか?はい、もちろんです!実際、このようなマクロ定義にはさまざまな用途があります。最も顕著なのは、コマンドの星印の付いたバリアントの基本的な定義です。たとえば、article
定義\section
\newcommand\section{\@startsection {section}{1}{\z@}%
{-3.5ex \@plus -1ex \@minus -.2ex}%
{2.3ex \@plus.2ex}%
{\normalfont\Large\bfseries}}
どのようにかかるか見てみましょうゼロ\section[<toc>]{<title>}
引数は、通常は?!として指定/使用しますが、\@startsection
6つの引数を取り、ユーザーが星を追加したかどうかをテストするためです。latex.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}}}}
そのため、通常指定する引数は、\section
2 段階後のマクロによってのみ取り込まれます。
これが良い方法である理由のもう一つの良い例は、カテゴリコードの変更に関係しています。引数が使用されると、カテゴリコードは変更できません。そのため、カテゴリコードを変更するには、通常、ヘルパーマクロが使用されます。前にあらゆる議論を呑み込む。
他にも数多くの例がありますLaTeXカーネル基本的なフォント マクロから ToC の処理、さらには による新しいコマンドの定義まで、さまざまな機能を提供します\newcommand
。
\def\newcommand{\@star@or@long\new@command}
これも引数を取らないマクロですが、別のマクロに処理を渡す前に何らかの操作を実行します。一般に、この原則はカーネルとパッケージ全体で広く使用されています。
答え2
Werner の回答で説明されているように、これは一般的な方法です。 * バリアントを持つすべてのマクロは、次のように定義されます。
\newcommand{\foo}{\@ifstar{\@sfoo}{\@foo}}
\newcommand{\@sfoo}[1]{Foo with * applied to #1}
\newcommand{\@sfoo}[1]{Foo without * applied to #1}
またはその変形。同様に、オプション引数を複数持つマクロ (例: ) では、\makebox
オプション引数が 0 個か 1 個か 2 個かを判断するために長い手順を踏む必要があります。
\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}
状況xparse
は全く異なります。*バリアントとオプションの引数はかなり一般的な方法で指定できるため、全て実際の引数:
\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}%
}%
}%
}
これが LaTeX3 の「未来」です。