前回の記事の後にいくつか反応をいただいたので、この記事で補足訂正する。
目次
\noexpandと\expandafter
前回の記事では\noexpandは「コマンド名にnoexpandマークをつけ、noexpandマークのついたトークンの意味は\relaxと(ほとんど)同じになる」としたが、それでは説明できない実行結果をいただいた。
🤔🤔🤔#TeX #TeX言語 pic.twitter.com/ekCleqFR4Y
— 🙃ZR-TeXnoナンチャラ🙂 (@zr_tex8r) June 24, 2018
実際に試したところ、
$ pdftex This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2018) (preloaded format=pdftex) restricted \write18 enabled. **\def\foo{FOO!} entering extended mode *\message\expandafter{\noexpand\foo} \foo *\message\expandafter\expandafter\expandafter{\noexpand\foo} FOO!
となり、確かに2回展開(\expandafter3個)すると\noexpandの効果が切れているのがわかった。ただ、これでは「2回展開の結果、\fooが展開された」のか「2回展開の結果、noexpandマークが外れた」のかがわからない(\messageはどっちみち引数を展開しようとするので)。
そこで、\unexpandedを組み合わせて、\expandafterの結果をそれ以上展開せずに表示させよう。
*\message{\unexpanded\expandafter{\noexpand\foo}} \foo *\message{\unexpanded\expandafter\expandafter\expandafter{\noexpand\foo}} \foo *\message{\unexpanded\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\noexpand\foo}} FOO!
最初の実行例、\expandafterが1個のやつは\noexpandを1回展開しており、展開結果は我々の仮説では「noexpandマークのついた制御綴\foo」となる。
\expandafterが3個(2回展開)の場合は「noexpandマークのついた制御綴\foo」を1回展開する。この展開結果も\fooであるが、この\fooにnoexpandマークがついているかは不明である。ともかく、この時点(\noexpandの2回展開/noexpandマーク付きのトークンの1回展開)では\fooは展開されない。
\expandafterが7個(3回展開)の場合は\fooが展開されている。
あるいは、\showを使えばより直接的に確かめられるだろう:
*\expandafter\show\noexpand\foo > \foo=\relax. <recently read> \notexpanded: \foo <*> \expandafter\show\noexpand\foo ? *\expandafter\expandafter\expandafter\show\noexpand\foo > \foo=macro: ->FOO!. <recently read> \foo <*> ...r\expandafter\expandafter\show\noexpand\foo ? *\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\show\noexpand\foo > the letter F. \foo ->F OO! <*> ...r\expandafter\expandafter\show\noexpand\foo ?
これらの結果は、「noexpandマークのついたトークンを\expandafterで一回展開した場合、noexpandマークが外れる」ことを意味している。
\expandedの今
前回の記事では\expandedはまだpdfTeXに入っていないと書いたが、
ちなみに、最新のpdfTeXには、\expanded が存在する。#TeX pic.twitter.com/2QcOpLoafL
— 🙃ZR-TeXnoナンチャラ🙂 (@zr_tex8r) June 24, 2018
とのことである。
筆者はTeX Live 2018のpdfTeXで確認したので\expandedがまだだと思ったのだが、どうもその後(TeX Live 2018以後)実装されていたようだ。
pdfTeXの\expandedプリミティブは割と最近(今年の5月)ようやく実装されたがTeX Live 2018には入っていない(W32TeXには入っている?)という感じだろうか https://t.co/Mjk06awu6y https://t.co/dqlY8zdCae (メーリングリストのアーカイブのドメインの証明書の期限が切れているっぽい)
— 新オフトゥン生活 (@mod_poppo) June 25, 2018
メーリングリストの投稿:
SVNのコミット:
- pdftex r801
- texlive r47741 (pdftex)
- texlive r47745 (eptex)
[tex-live]に投げられたメールによると、expl3を開発する上で\expanded(や、その他いくつかのプリミティブ)が使えると便利、みたいな話なので、\expandedはpdfTeXだけでなくXeTeXやe-pTeX等にも実装される模様である。