「# 表記」とは何ですか? # 構文はどのように機能しますか?

「# 表記」とは何ですか? # 構文はどのように機能しますか?

密接に関連:\expandafter と同様に \expandbefore を実装するにはどうすればよいでしょうか?

関連する質問では、 が参照されています"# Notation"。構文はどのように機能しますか?

他の質問に対する回答から:

\makeatletter
%
\newcommand\name{}%
\long\def\name#1#{\UD@innername{#1}}%
%
\newcommand\UD@innername[2]{%
  \expandafter\UD@exchange\expandafter{\csname#2\endcsname}{#1}%
}%
%
\newcommand\UD@exchange[2]{#2#1}%
%
\makeatother

パラメータ構文 (数字なし) は実際にどのように機能しますか? \def\test#1#{\csname test#1\endcsname}? このパターンを使用するのに適したユースケースは何ですか?

答え1

要点は次のとおり\nameです。

\name⟨stuff without braces before the left-brace⟩{⟨stuff within braces⟩}

TeXは最初の引数として取得し⟨stuff without braces before the left-brace⟩、2番目の引数として処理します⟨stuff within braces⟩:

は、結果の式にラップして実行する⟨stuff within braces⟩ことで取得できる制御シーケンス トークンの名前として使用されます。⟨stuff within braces⟩\csname..\endcsname\csname..\endcsname

その代わりに、制御シーケンス トークンが後ろに来ます。{⟨stuff within braces⟩}⟨stuff without braces before the left-brace⟩


区切られた引数を持つマクロが実行されると、(La)TeX はトークン ストリームから引数を形成するトークンを収集し、トークン ストリーム内で引数区切り文字を検索します。引数区切り文字は、問題の引数のトークンを収集するプロセスを終了するためのマーカーとして使用されます。

検索する区切り文字は、⟨パラメータテキスト⟩定義の。

最後の引数(例えばa)を区切り\relax文字として検索するように(La)TeXに指示するには、次のように記述します。\relax⟨パラメータテキスト⟩

#最後の引数の区切り文字として、(La)TeXが左括弧を検索することを示すことができます。⟨パラメータテキスト⟩

(ほぼ;-))いずれにせよ、⟨パラメータテキスト⟩マクロ定義の後に⟨置換テキスト⟩、中括弧で囲まれています。
したがって、(ほぼ;-))いずれにしても、⟨パラメータテキスト⟩マクロ定義の末尾には、マクロ定義を囲む中括弧の左括弧が続きます。⟨置換テキスト⟩.
したがって、最後のトークンが⟨パラメータテキスト⟩が である場合#、その後に が続きます{
そのため、(La)TeX がマクロの最後の引数を収集するときに区切り文字として左中括弧を検索することを示すこのものは、#{-記法とも呼ばれます。

\relax開き括弧の検索と検索の微妙な違いは次のとおりです。

たとえば、マクロの引数の区切り文字として (La)TeX が を検索して\relaxそれを見つけると、引数のトークンの収集を停止するだけでなく、区切り文字/トークンも削除します\relax

マクロの最後の引数の区切り文字として(La)TeXが左括弧を検索してそれを見つけると、最後の引数のトークンの収集は停止し、その区切り文字/括弧はそのままにして、マクロの⟨置換テキスト⟩その前に。


ドナルド・アーヴィン・クヌース教授のTeXbook第20章「定義(マクロとも呼ばれる)」からの引用—ドナルド・アーヴィン・クヌース教授、スタンフォード大学のコンピュータプログラミングの名誉教授は、TeX の発明者です。

これまでいくつかの例を見てきましたが、TeXマクロを規定する正確なルールを見てみましょう。定義は一般的に次の形式です。

\def⟨制御シーケンス⟩⟨パラメータテキスト⟩{⟨置換テキスト⟩}

どこ⟨パラメータテキスト⟩括弧は含まれておらず、{そして }の中に⟨置換テキスト⟩適切にネストされています。さらに、# 記号には特別な意味があります。 ⟨パラメータテキスト⟩、最初の#の後に1が続き、次の#は2、というように続く必要があり、最大9つの#が使用できます。⟨置換テキスト⟩ 各#の後に、#の後に現れる数字が続く必要があります。⟨パラメータテキスト⟩そうでなければ、# の後に別の # を続ける必要があります。後者の場合は、マクロが展開されるときに単一の # トークンを表します。前者の場合は、対応する引数の挿入を表します。

[...]

これらのルールには特別な拡張が認められています。⟨パラメータテキスト⟩は # なので、この # の直後に {、TeXは、{パラメータテキストと置換テキストの両方の右端に挿入されます。たとえば、
\def\a#1#{\hbox を #1 へ}'
の場合、 \a の引数が左中括弧で区切られているため、後続のテキスト '\a3pt{x}' は '\hbox to 3pt{x}' に展開されます。

言い換えると:

と言えば、後続のテキストは次のように処理されます。\def\a#1#{\hbox to #1}\a3pt{x}

マクロの引数として、\aTeXは後続のテキストから左中括弧で区切られた引数を収集します。これはフレーズを収集します3pt
左中括弧(およびその後ろのすべて)はそのまま残り、\aその引数は次のように置き換えられます。⟨置換テキスト⟩結果は\hbox to 3pt次のようになります。 全体は次のようになります\hbox to 3pt{x}


簡単に言うと、#{- 表記 (左中括弧に注意!) は、問題のマクロの最後のパラメータが左中括弧 (カテゴリ コード 1 (グループの開始)) で区切られ、(La)TeX がトークン ストリームからそのマクロの最後の引数を収集するときにそのまま残されることを意味します。

この特殊なケースでは区切り文字、つまり左中括弧がそのまま残されるという事実は注目に値します。これは、引数を収集するプロセス中に引数区切り文字がトークン ストリームから削除されない唯一の状況だからです。

つまり、引数区切り文字が、例えば、次\relaxのように -トークンである場合、

\def\mymacro#1\relax{The Argument#1 was delimited by relax. }

\relaxトークンストリームから引数を収集するときに区切り文字として機能するトークンが削除されます。

\mymacro , which is nonsense,\relax...

の引数として、\mymacro(La)TeXはトークンストリームからシーケンスを収集し, which is nonsense,、トークンを見つけて\relaxそのトークンを引数の区切り文字として取得します\relax。そのため、(La)TeXは引数のトークンの収集を停止し、区切り文字を削除します。(その後、\mymacroifの他の引数の収集を開始します。⟨パラメータテキスト⟩定義上、何も存在しない。しかし、存在しない。⟨置換テキスト⟩:

The Argument, which is nonsense, was delimited by relax. 

これ⟨置換テキスト⟩トークン ストリームの末尾には 3 つのドットが付くため、トークン ストリームには次の内容が含まれるようになります。

The Argument, which is nonsense, was delimited by relax. ...

しかし、定義が次の通りであれば、

\def\mymacro#1#{The Argument#1 was delimited by a left-brace. }

そしてあなたは言う

\mymacro , which is nonsense,{...

、あなたは得るでしょう

The Argument, which is nonsense, was delimited by a left-brace. {...

なぜなら、前者の場合、\relax引数を区切る が削除されるのとは異なり、この場合は、引数を区切る左中括弧は削除されないからです。


フレーズ

最後の文字が⟨パラメータテキスト⟩は # なので、この # の直後に {、TeXは、{パラメータテキストと置換テキストの両方の右端に挿入されていました。

手段:

定義は通常パターンである

\def⟨制御シーケンス⟩⟨パラメータテキスト⟩{⟨置換テキスト⟩}

\macro最初の引数が区切られておらず、2 番目の引数がシーケンスによって区切られている 2 つの引数を処理し\foo\bar、引数を単に「吐き出す」 マクロを定義したいとします。

この場合、次のような式を作成します。

\def\macro#1#2\foo\bar{argument 1: #1 argument 2: #2}

⟨制御シーケンス⟩=\macro

⟨パラメータテキスト⟩=#1#2\foo\bar

⟨置換テキスト⟩=argument 1: #1 argument 2: #2

この表現を見ると、右端の⟨パラメータテキスト⟩最後の引数の区切り文字となるトークンが存在する。、つまりトークン\foo\barである。これらは、⟨パラメータテキスト⟩すぐ後ろには、左側の支柱が見えます。⟨置換テキスト⟩この場合、
右端に⟨パラメータテキスト⟩最後の引数を区切るトークンを見つけ、引数を囲む括弧のペアの左括弧を見つけます。⟨置換テキスト⟩

シーケンス

\macro{A}B\foo\bar

結果:

argument 1: A argument 2: B

ご覧のとおり、\foo\bar引数に属するトークンを収集する際に区切りトークンが削除されました。

代わりに次のように定義します:

\def\macro#1#2\foo\bar{argument 1: #1 argument 2: #2\foo\bar}

⟨制御シーケンス⟩=\macro

⟨パラメータテキスト⟩=#1#2\foo\bar

⟨置換テキスト⟩=argument 1: #1 argument 2: #2\foo\bar

つまり、区切り文字を\foo\bar文字列の右端に挿入すると、⟨置換テキスト⟩また、 シーケンス

\macro{A}B\foo\bar

収穫

argument 1: A argument 2: B\foo\bar

以前の定義では区切り文字がそのまま残されていたかのように

そのようなものを定義したいが、区切り文字がシーケンスではなく\foo\bar左中括弧である場合はどうなりますか?

定義は依然としてパターンであるべきである

\def\macro#1#2⟨delimiter⟩{argument 1: #1 argument 2: #2⟨delimiter⟩}

しかし、いくつかの理由から{⟨デリミタ⟩そして書く

\def\macro#1#2{{argument 1: #1 argument 2: #2{}

そして、ここ#1#2{⟨パラメータテキスト⟩そしてargument 1: #1 argument 2: #2{⟨置換テキスト⟩:

  1. 多くの場合、中括弧のバランスが崩れているためにエラーが発生することなく、単一の左中括弧を簡単に挿入することはできません。

  2. この状況は曖昧になる。なぜなら、(La)TeXは、⟨パラメータテキスト⟩引数区切り文字であるか、または引数を囲む中括弧のペアに属しているか⟨置換テキスト⟩
    (La)TeXは、右括弧が行末の左括弧と一致するかどうかを推測する必要もある。⟨置換テキスト⟩あるいはそれが⟨置換テキスト⟩

そのため、構文上の回避策として#{-記法が考案されました。

\def\macro#1#2#{argument 1: #1 argument 2: #2}

⟨制御シーケンス⟩= \macro.

⟨パラメータテキスト⟩=#1#2#

⟨置換テキスト⟩=argument 1: #1 argument 2: #2

⟨パラメータテキスト⟩{最後の引数を区切るトークンで終わっていませんが、 で終わっています#

これは、(La)TeXがトークンストリームから最後の引数のトークンを集める#プロセス中に、引数区切りとして左括弧を検索することを示すために使用されます。また、区切りとして見つかった左括弧はそのまま残され、\macro\macro#⟨置換テキスト⟩of が\macroその前に来ます。

言い換えると:

これ#により、(La)TeXは、最後の引数を区切る最後のトークンとして左括弧が見つかったかのように動作します。⟨パラメータテキスト⟩

また、(La)TeXは定義の最後のトークンが⟨置換テキスト⟩左括弧でした。


あなたのコメントへ:

うーん。何かでっち上げることはできないでしょうか? 何が起こっているのか、できるだけ正確に推測できますか? 言い換えると、他の例で、この中に cat code 1 の文字が浮かんでいるとします。この「基本的な動作」は、ファイル読み取りの入力フェーズで発生していると推測してよいでしょうか? (申し訳ありませんが、用語を適当にでっち上げています... イベントprocess_input_bufferハンドラーのことを言っています。

LaTeXの処理の最初の段階は、入力(ファイルまたはコンソールから)を読み取り、それを一連の命令として解釈して、トークントークンストリームに挿入されます。(文字トークン/制御シーケンストークン)。後続のステージでは、トークンストリーム内のトークンが処理されます。これらのステージの前の 1 つでは、拡張可能なトークン (マクロなど) が展開されます。つまり、それらのトークンは、定義の置換テキストを形成するトークンに置き換えられます。このステージでは、マクロ引数のトークンの収集が行われます。したがって、この動作は、ファイルの読み取り時には行われませんが、読み取りとトークン化の後に、拡張可能なトークンを展開し、それによって他のトークンを収集するステージで行われます。トークン彼らの主張どおり。


私は質問に対する回答で、(La)TeXがマクロ引数を収集して処理する方法を詳しく説明しようとしました。TeX は区切られた引数をどのように検索しますか?

\expandafter私は質問に対する回答の中で、それを避ける方法を詳細に説明しようとしました。csname マクロに追加するときに、expandafter の数を知るにはどうすればよいですか?

\name私は質問に対する回答の中でマクロについて詳しく説明しようとしましたスペースが重要になる制御シーケンスを定義します

関連情報