\@firstofone を理解する

\@firstofone を理解する

私はこの回答に目を通し、コードを理解しようとしていました。私は LaTeX の超初心者 (2 日目) で、コードの次の部分で行き詰まり、テーブル環境以外では動作させることができませんでした。私が理解できないことの最も単純な形は次のとおりです。

\documentclass{article}
\begin{document}
    \newcommand*\f[3]{#1-#2-#3}
    \newcommand*\ex[1]{\f#1 - \expandafter\f\@firstofone}
     Try \ex{111}{221}
\end{document}

何らかの理由で、リンクされたコードでは、最後の引数が消費されず、コンストラクトによって消費されるままになっていますexpandafter\f\...。私の理解では、まず を「実行」して、引数を取得し、括弧を削除して に渡す\expandafter必要があります。これは実行されず、その理由がわかりません。 \@firstofone{221}\f

答え1

これを機能させるには使用する必要があります\makeatletterが、最小限で済みます。

呼び出しは\ex{111}{221}まず

\f 111 - \expandafter\f\@firstofone{221}

ここで\fが展開され、 、 という 3 つの引数が検索されます。1これ11、TeX では中括弧が欠落している場合に単一のトークンが使用されるためです。

の定義により、\fこれが展開され、置換テキストが入力ストリームに再挿入されます。

1-1-1 - \expandafter\f\@firstofone{221}

トークンは1-1-1 -拡張できないため、次のステージに送られます。

\expandafter\f\@firstofone{221}

これは\f\@firstofone(括弧なしの引数)を返すだけなので、

\f221

となる2-2-1。したがって、コードの最終的な効果は、

1-1-1 - 2-2-1

あまり役に立たないようです。どこで見つけたとしても、信用しないでください。

答え2

egregが回答で指摘したように、の使用は\@firstofoneあまり役に立たず、この特定のケースでは違いはありません。しかし、それが役立つ場合もあります。便利です。完全を期すために、2 つの例を挙げたいと思います。

拡張可能なマクロ

なぜ\expandafter\@firstoftwo慣用句なのですか?\@firstoftwo完全に展開可能なマクロでのとの典型的な使用例\@secondoftwoを示します。 は\@firstofone、LaTeX の「恒等関数」の一種であり、単一のパラメータのみを処理する同様のコンテキストで役立ちます。

\def\gobbleIfZero#1{%
  \ifnum#1=0
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
}

foo\gobbleIfZero{0}{bar}

foo\gobbleIfZero{123}{bar}

あげる

フー

フーバー

\@gobble( のように\@firstofone) は単一のパラメータを取りますが、それを破棄して「nothing」に展開します。

カタログコードの修正

もう少しトリッキーですが、より興味深いのは、catcode の変更が関係する場合です。TeX がマクロの引数を解析しているとき、引数テキストが読み取られるたびに catcode を修正します。ここでは catcode の変更がないため、これは問題になりません。ただし、次のようなやや不自然な例があるとします。

\begingroup
\catcode`4=\active
\gdef 4{four}
\endgroup

\newcommand*\f{\catcode`4=\active}
\newcommand*\exA{\f}
\newcommand*\exB{\expandafter\f\@firstofone}

{\exA{345}--{345}}

{\exB{345}--{345}}

その結果、

3four5-3four5

345-3four5

4最初の 4 行は、 に展開されるグローバル マクロを定義しますfour。通常は4catcode 12 (その他) なので、マクロを作成できるように 13 (アクティブ) に変更します。\fここでは、実行時にこのマクロをスコープに戻します。

が実行されると\exA、 の catcode は413 に変更され、その後、次の 2 つのグループの両方で4に展開されますfour。ここにはパラメーターがまったくないため、これは簡単です。

一方、\exBマクロでは最初の部分は同じテキストを返すだけ{345}で処理されます。\@firstofoneしかし、catcodeを修正します12に変更します4。一度修正すると、変更できなくなります。catcodeの変更が\f処理されても前に最初のグループ345には影響はありません。2 番目のグループの catcodes は{345}まだ修正されていないため、このグループには変更が適用されます。

この動作は、catcodeの変更を処理する既存のマクロに追加のコードを挿入したい場合に非常に便利です。たとえば、\verbこのTeXの真珠):

\begingroup
\catcode`\/\active
\catcode`\_\active
\@firstofone{%
  \verb|%
  \catcode`\/\active \def/{\par}%
  \catcode`\_\active \def_#1_{\textcolor{blue}{#1}}%
}_\documentclass_{article}/_\begin_{document}/  We all love _\LaTeX_!/_\end_{document}|
\endgroup

出力

出力

\@firstofoneそもそもどこで読んだのかはわかりませんが、おそらくこれらのいずれかの文脈で読んだのでしょう。

関連情報