マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

10分でわかる \futurelet

TeX言語🤮でよくネタにされるものとして\expandafter\aftergroupといった“変態的なプリミティブ”がある。今回のテーマである\futureletもその“変態的なプリミティブ”の一種として紹介されることが多い。

ところが実は\futurelet「その動作を理解するだけ」であればそんなに難しいものではない。特に「他人が書いた\futureletを含むコードの動作を把握したい」という場合は、\futureletの定義さえ知っていれば「とにかく定義に愚直に従って動作を把握する」ことができる。\futureletが“読める”ことはそれだけでも大きなメリットになるだろう。

そういうわけで、本記事では\futureletの動作を理解したうえで、その知識を使って実際に\futurelet“読む”ことを目標とする。

前提知識

  • TeX言語の「トークン(token)」とは何かを理解している。
  • \letプリミティブの動作を理解している。

とにかく \futurelet の規則を知ろう

\futureletの動作を把握するには「TeXのコードをトークンの列”として見る」ことが大事である。\futureletが実行される場面において、実際に\futurelet以降のコードを“トークンの列”と考えてみよう。

\futurelet‹トークン1›‹トークン2›‹トークン3›‹トークン4›……

この前提の下で、「\futurelet‹トークン1›」という文は、以下の動作を行う。

  • この文の2つ先にあるトークン、すなわち‹トークン3›‹トークン1›\letする1

注意として、(少なくとも本記事の定義では2\futureletの“引数”に相当するのは‹トークン1›だけであるので、文を実行した後も‹トークン2›‹トークン3›そのまま残っている。従って、この文の次には‹トークン2›が実行されることになる。

補足

  • \futureletは代入文の一種である。従って、一般の代入文についての諸々の注意事項(\global修飾や\afterassignmentなど)は\futureletについても当てはまる。

とにかく \futurelet するコードを読もう

\futureletの規則を把握したので、次はその規則を使って\futureletを使った簡単なコードを“読む”練習をしてみよう。以下のコードにおいて、マクロ\Checkが何をするものなのかを言葉で説明してほしい。

\def\Check{\futurelet\my@tok\my@check@a}
\let\my@bgroup={ %←暗黙文字トークン
\def\my@check@a{%
  % \my@tokが'{'であるなら...
  \ifx\my@tok\my@bgroup \message{Yes}%
  \else \message{No}%
  \fi}

読んでみる

パッと見たところでは\Checkは引数を取らないようなので、\Check単体で展開を追ってみる。

\Check
↓(展開)
\futurelet\my@tok\my@check@a

\futureletの規則を愚直に適用すると、\futurelet\my@tokが実行されるとその文の2つ先にあるトークンを見ることになるが、今考えている範囲では、文の後にあるトークンは1つしかない。結局、\Checkの直後に何かトークンがある状態を考える必要があったようである。\Checkの直後のトークンを‹トークンA›とする。

\Check‹トークンA›…

\Checkを展開すると以下のようになる。

\futurelet\my@tok\my@check@a‹トークンA›…

改めて\futureletの規則を適用すると、\futurelet\my@tokを実行すると、2つ先にある‹トークンA›\my@tok\letされる3。その後の入力バッファは以下のようになる。

\my@check@a‹トークンA›…

これ以降は\my@check@aの展開・実行となる。\my@check@aは単純なコードなので、以下の動作をすることは容易に理解できるであろう。

  • \my@tokの意味が(カテゴリコード1の){に等しいかを調べて、そうであればYes、なければNoを端末に出力する。

ここで\futureletの実行により「\my@tokの意味」は「‹トークンA›の意味」と等しくなっている。従って、\my@check@aは実質的には‹トークンA›の意味を調べていることになる。

これで\Checkのコードを完全に“読む”ことができた。結局、\Checkの動作を言葉で説明すると以下のようになる。

  • 自身の直後にあるトークン(の意味)が(カテゴリコード1の){に等しいかを調べて、そうであればYes、なければNoを端末に出力する。

まとめ

もうこれで、読んでいるコードの中に\futureletが出てきてもコワくありません! どんどんTeX言語🤮のコードを読んでいきましょう💁


  1. 要するに\let‹トークン1›‹トークン3›に相当する動作を行う。もっと厳密にいうと「\let‹トークン1›=␣‹トークン3›」と同値になる(‹トークン3›=や空白トークンである場合まで考慮するとこの形で書く必要がある)。
  2. ‹トークン3›までを\futureletの引数とする考え方もある。なお、コードを整形する目的では「\futurelet‹トークン1›‹トークン2›」までを一つの文として扱うことが多い。
  3. つまり\let\my@tok=␣‹トークンA›が実行される。