別のディスカッショントピックとしてご質問をさせていただきました:
\noexpand の動作は、どのように考えるとよいか
2023年 03月 31日(金曜日) 13:54 - ut の投稿
https://okumuralab.org/tex/mod/forum/discuss.php?d=3563
について考えてみるに際しては、以下のページを参考にしていました:
--------------------------------------------------------------------------------
Tralics: a LaTeX to XML translator
http://www-sop.inria.fr/marelle/tralics/
というページにある:
HTML documentation of all TeX commands, in alphabetic order
の中の "N" のページの \noexapnd の説明:
http://www-sop.inria.fr/marelle/tralics/doc-n.html#cmd-noexpand
--------------------------------------------------------------------------------
このページでは、\noexpand の説明をするのに、例を 10 パターン列挙しているのですが、
そのうちの 7 番目 ~ 10 番目が、実はよく理解できませんでした。
該当箇所には以下のようにあります(勝手に番号を振り、例を説明文のすぐ後ろに移動し
ました.また、to と spread には引用符を付けました):
--------------------------------------------------------------------------------
(7) In the line that follows, expansion is inhibited while scanning the "to" keyword.
Hence \foo is expanded again and is considered as an opening brace.
\def\foo{\bgroup}\hbox\noexpand\foo x\egroup
(8) In the line that follows, the second \noexpand is eaten by scanning the "spread"
keyword. So it requires three \noexpand in order to discard \foo.
\hbox\noexpand\noexpand\foo y\egroup
\hbox\noexpand\noexpand\noexpand\foo{z}
(9) In the two lines that follow, the non-expanded \foo terminates scanning of
the number, and becomes part of the unit of measure.
\def\foo{pt} \dimen0=2\noexpand\foo
\def\foo{.5pt} \dimen0=2\noexpand\foo % error
(10) Consider the last line: how many \noexpand tokens are needed to effectively
suppress expansion (and provoke an error)?. Quite a lot: ... and 15 in TeX.
The syntax of a dimension is quite complicated (see scandimen) and each time
an optional thing is tried, one \noexpand is eaten. For instance, one could
have em, ex or true. After that ... TeX scan eleven keywords, one after the other.
%\def\foo{sp} \dimen0=2\noexpand\noexpand...\foo
--------------------------------------------------------------------------------
質 問
(7) と (8) を素朴に読みますと、\hbox の後ろでは、まず "to" があるかどうかがスキ
ャンされて、次に "spread" があるかどうかがスキャンされていて、その度に \noexpand が
一旦呑み込まれる、ということのようなのですが、そういう理解でよいのでしょうか。
(9) と (10) についても、ディメンションを確定するには、単位の keyword が必要で、
pt, em, ex, in, pc, cm, mm, bp, dd, cc, sp の 11 個のうちのどれかがちゃんとあるか
どうかが順番にスキャンされていって、その度ごとに \noexpand が一旦呑み込まれる、と
いうことなのでしょうか。
(あと 4 つは、何? true?, mu?, by?, minus?, plus?, fil?)
※ 興味本位での質問ですので、格別今、何か困っているというわけではありません。
(tex.web を読んでみているのですが正直よくわかってません……)
\noexpand
は次のトークンを読んで、入力に戻し、さらにそのトークンがコントロールシーケンスだったら次にそのトークン読まれるときに noexpand なトークンとして読まれるように細工するみたいです。
keyword のスキャン中に keyword にマッチしない展開できないトークンを見つけると、そのトークン(とそれまでにマッチした文字トークン列)は入力に戻されますが、この時は上記のような細工はされないので次に入力から読まれるときは noexpand ではない状態で読まれるのだと思います。
- "to" のスキャン中、
\noexpand
が展開され、\foo
が読み込まれ、\foo
が入力に戻され、さらに次に\foo
が読み込まれるときに noexpand になるように細工が行われる。 - "to" のスキャンは続いていて noexpand な
\foo
が読み込まれ、keyword にマッチしない展開不能トークンなので読み込んだ\foo
を(細工なしで)入力に戻し "to" のスキャンが失敗で終了する。 - "spread" が開始され、(細工なしの)
\foo
が読み込まれ、\foo
が\bgroup
に展開され、keyword にマッチしない展開不能トークンなので読み込んだ\bgroup
を入力に戻し "spread" のスキャンが失敗で終了する。
ということなのではないか、と思います。
(tex.web をもっとちゃんと読んで処理を追いかければ正解がわかるんでしょうけれど……)
(10) について、私の tex(TeX Live 2023 Windows版)では \noexpand
が 14 個でエラーになります。
スキャンされる keyword は em, ex, true, pt, in, pc, cm, mm, bp, dd, cc, sp の 12 個だと思います。(\foo
の中身と \noexpand
の数をいろいろ変えるとどの keyword が何番目にスキャンされているか推測できるかと。)
これ以外に
- 2 に続く数字のスキャン(整数のスキャン)
- 2 に続く小数点のスキャン(小数部のスキャン)
で先頭の 2 個の \noexpand
が食われていると思います。
ご回答をありがとうございます!
(早々にお返事くださいましたのに、応答迅速でなく申し訳ありません)
まず、\noexpand の動作を一言で説明するなら:
> \noexpand は次のトークンを読んで、入力に戻し、さらにそのト
> ークンがコントロールシーケンスだったら次にそのトークン読ま
> れるときに noexpand なトークンとして読まれるように細工する
と言えば良かったのですね。
それで:
> keyword のスキャン中に keyword にマッチしない展開できない
> トークンを見つけると、そのトークン(とそれまでにマッチした
> 文字トークン列)は入力に戻されますが
とのことですので、そもそもの話としてやはり、keyword が順番に
スキャンされているのですね。そして、スキャン中に遭遇したトー
クンは一旦呑み込まれた上で、マッチしないと戻されているわけで
すね。
引用元の文章でも、"scanning the to keyword"; "scanning the spread
keyword"; "15 in TeX"; "TeX scan eleven keywords" 等々とさらり
と書かれているのですけれど、そんな話初めて聞いたので、どこで
確認したらいいんだろう、と困惑しました。
> \foo の中身と \noexpand の数をいろいろ変えるとどの keyword
> が何番目にスキャンされているか推測できるかと。
(9) で \def\foo{pt} となっていて、(10) で \def\foo{sp} となっ
ていたので、最初にスキャンされるのが pt で、最後が sp なんだ
ろうな、とは推測していました(でも、em, ex, true のほうが先で
したか)
>(tex.web をもっとちゃんと読んで処理を追いかければ正解がわか
> るんでしょうけれど……)
うーん、最後はやはり tex.web を見なきゃいけないのですね。
(私には難し過ぎそうです)
いずれにしましても、今回もまた、大変丁寧にご説明をしてくださ
いまして、本当にありがとうございます。
(早々にお返事くださいましたのに、応答迅速でなく申し訳ありません)
まず、\noexpand の動作を一言で説明するなら:
> \noexpand は次のトークンを読んで、入力に戻し、さらにそのト
> ークンがコントロールシーケンスだったら次にそのトークン読ま
> れるときに noexpand なトークンとして読まれるように細工する
と言えば良かったのですね。
それで:
> keyword のスキャン中に keyword にマッチしない展開できない
> トークンを見つけると、そのトークン(とそれまでにマッチした
> 文字トークン列)は入力に戻されますが
とのことですので、そもそもの話としてやはり、keyword が順番に
スキャンされているのですね。そして、スキャン中に遭遇したトー
クンは一旦呑み込まれた上で、マッチしないと戻されているわけで
すね。
引用元の文章でも、"scanning the to keyword"; "scanning the spread
keyword"; "15 in TeX"; "TeX scan eleven keywords" 等々とさらり
と書かれているのですけれど、そんな話初めて聞いたので、どこで
確認したらいいんだろう、と困惑しました。
> \foo の中身と \noexpand の数をいろいろ変えるとどの keyword
> が何番目にスキャンされているか推測できるかと。
(9) で \def\foo{pt} となっていて、(10) で \def\foo{sp} となっ
ていたので、最初にスキャンされるのが pt で、最後が sp なんだ
ろうな、とは推測していました(でも、em, ex, true のほうが先で
したか)
>(tex.web をもっとちゃんと読んで処理を追いかければ正解がわか
> るんでしょうけれど……)
うーん、最後はやはり tex.web を見なきゃいけないのですね。
(私には難し過ぎそうです)
いずれにしましても、今回もまた、大変丁寧にご説明をしてくださ
いまして、本当にありがとうございます。