もう2週間ほど前のことになりますが,10月14日(土)に開催された TeXConf 2017 に参加してきました.私は一般講演枠を1つ頂いていて『expl3 入門』というタイトルで,その名の通り expl3 という言語のチュートリアル講演を行いました.その際の発表資料がこちらです.
そもそも一般講演を申し込んだ理由が「講演という “締め切り” を設定することで,自分が expl3 の勉強をしたいから」というところにあったこともあり(発表駆動),かなり直前になってドタバタと突貫で準備を行ったわけですが,幸いにもご好評を頂くことができました.
そして発表後の質疑応答では6つほどの質問を頂戴しました.しかし,時間の関係と私の知識不足により,その場では最低限度の回答しかできなかったものもありました.そこで,本稿では頂いた質問に再度答える Q&A の形をとって,少し詳細な補足をしてみようと思います.
注意:質疑応答の時間中にメモをとっていたわけではないので,実際に頂いた質問とは少し表現や論点が異なる可能性があります.また,質問の順番は恣意的に入れ替えています.予めご了承ください.
Q1. 引数指定子 w
の使用例は \exp_after:wN
以外にもあるか?
はい,あります.
その場では具体的な例を挙げることはできませんでしたが,expl3 の公式ドキュメント(interface3.pdf)には内部関数も合わせて少なくとも76個 <arg-spec>
に w
を含む関数が掲載されています1.
引数指定子 w
は expl3 の文法上「例外」とされる引数形状を表すもので,具体的には
- un-balanced を許容する1トークン
- 特定のトークン(デリミタ)までのトークン列
- TeX 式の条件分岐
などを含みます.
TeX 言語の \expandafter
が代入された expl3 の関数 \exp_after:wN
はこのうち1つ目に該当します.
2つ目のケースには,TeX 言語の \csname
にあたる \cs:w
などが含まれます2.
expl3 では基本的に引数指定子 T
や F
を含むより高級な条件分岐関数の使用が好まれますが,TeX 式の \if ... \else ... \fi
のような形で用いられる関数がいくつか存在し(\if:w
など),これらが3つ目のケースに該当します.
Q2. 型が間違っている場合,エラーや警告は出るのか?
必ずエラーや警告が出るとは限りません.
理論上はある程度「型エラー」を出すことは可能ですが,現時点ではそもそも各関数はきちんと引数の型をチェックしていないようです.そのため,本来 <t>
型の引数を1つとる関数 f_<t>
に <u>
型の引数が渡された場合,以下のパターンのうちのどれかが発生すると考えられます:
- 関数
f_<u>
が存在しない場合- TeX レベルの Undefined control sequence エラーが発生
- 関数
f_<u>
が存在する場合- 関数
f_<u>
の内部処理の途中で expl3 レベルもしくは TeX レベルのエラーが発生 - そのまま処理は通ってしまう(ただし,意図する結果になるとは限らない)
- 関数
このうち「関数 f_<u>
が存在する場合」については,expl3 の実装次第では適切な「型エラー」を出すことができる可能性が高いです.一方で,「関数 f_<u>
が存在しない場合」の Undefined control sequence エラーは,expl3 実装の範疇ではまず打つ手がないと思われます.
Q3. lint のようなプログラムは存在するか?
私の知る限り,存在していません.
expl3 言語の仕様は長いこと不安定な状態が続いていたこともあり,lint に限らず expl3 周辺の開発環境はまだまだ十分整備されているとは言えません.しかしながら,Q2 にあった型エラー問題などは expl3 コードを静的に解析することで(ある程度)検出できるはずなので,今後そういったプログラムが開発される可能性はあると思います.
Q4. LaTeX3 と ConTeXt の違いは?
いずれもポスト LaTeX2e を目指す TeX ベースのシステムという意味では目的を同じくするプロジェクトと言えますが,アプローチの方法がまったく異なります.
LaTeX2e 最大の問題点の1つに「レイアウトをいじろうと思うと,かなりの確率で(難解な)TeX 言語を書く必要がある」ということが挙げられます.LaTeX3 プロジェクトはこの問題を解決するためにプロジェクト全体を
- 文書マークアップ
- レイアウト設計
- プログラミング
の3階層に分け,それぞれの目的のために異なるインターフェース(言語)を用意するとしています.一方,ConTeXt は “author as designer” という考えに基づき,文書マークアップとレイアウト設計を分けることはせず,文書作成者自身がレイアウトを簡単に変更できるようなインターフェースを用意します.
また,LaTeX3 は(その気があれば)ユーザ自身が expl3 を用いてパッケージを作ることを推奨しますが,ConTeXt のすべての機能の実装は原則として限られた ConTeXt チームのメンバーのみで行うことになっており,ここにも大きな「哲学」の違いがあると言うことができると思います.
さらに,より低レベルな視点でも両者には大きな違いがあり,例えば LaTeX3 は pdfTeX, XeTeX, LuaTeX, e-(u)pTeX など多くの処理系をサポートするのに対して,ConTeXt は基本的に LuaTeX を前提としているということが挙げられます.
この件についてのより詳しい議論は,過去に Stack Exchange で行われているので,よろしければそちらも参照してみてください.
Q5. アンダースコアを数式で使用する場合はどうするのか?
expl3 の文法では _
を制御綴の一部として用いるということは,すなわち \ExplSyntaxOn
によって _
のカテゴリーコードが11に変更されているわけですが,では数式中で「下付き文字」を表現する場合にはどうするのかという質問です.
まず,簡潔かつ実用的にこの質問に答えるのであれば,l3token パッケージの機能を用いることで表現可能です.一番簡単な方法は _
の代わりに定数 \c_math_subscript_token
を用いることです.あるいは
\char_generate:nn{<charcode>}{<catcode>}
\char_set_catcode_math_subscript:N <char>
を用いる解決法もあると思います.
もう少し根本的な話をすると,_
1文字で「下付き文字」を表現するのは plain TeX や LaTeX2e の習慣ですが,LaTeX3 の文書マークアップについての仕様はまだほとんど何も決まっておらず,必ずしもこれまでのルールが踏襲されるとは限りません3.したがって,そもそも(将来の)LaTeX3 文書において _
が一般に数式中で使用されるかどうかは現時点では何とも言えないということは心に留めておく必要があります.
ところで,もし「LaTeX3 は3階層に分かれているので,expl3 コード中で数式を書くことはない」という解釈をしているとしたら,それは大きな勘違いです.LaTeX3 における上の2階層(すなわち文書マークアップ言語とレイアウト設計言語)は expl3 で実装されるものなので,expl3 を用いて「数式内で使用するための関数」を書くことはもちろんあり得ます.LaTeX3 の “階層分け” はあくまで「(LaTeX3 文書を作成する)ユーザが expl3 やレイアウト設計言語を直接書く必要がない」ということを意味しています.
Q6. 特定の処理系にしか存在しない機能は利用できないのか?
expl3 はいくつかの TeX 処理系をサポートしていますが,それらのプリミティブの差異を吸収しているため「expl3 でコードを書けばもれなくクロス・エンジンなコードになる」ということは私は発表中何度か強調したところです.逆に言うと,特定の処理系にしか存在しない機能は expl3 からは利用できないということか,というのがこの質問の趣旨だったと思います.
結論から言うと,利用できる場合もありますが,すべてではありません.
現在の expl3 バンドルには l3luatex パッケージが含まれており,これが提供する関数を用いると LuaTeX 固有の機能を利用することができます.一方で,LuaTeX 以外の処理系に固有の機能を利用するためのパッケージは,少なくとも今のところ LaTeX3 チームから公式には提供されていないようです.
おわりに:LaTeX3 コントリビュータになりました
かなり短期間で慌ただしく準備を行った『expl3 入門』講演でしたが,ここでご紹介した質問も含め,私が思っていた以上の反響と好評を頂くことができました.ありがとうございます.また,本講演を行って以来 Twitter 上では expl3 に関連する日本語のツイートが激増した模様で,少しでも LaTeX3 が日本国内で話題となったことを大変嬉しく思っています.
ところで,この講演の準備期間中 expl3 の公式ドキュメント(interface3.pdf)を読んでいる際に,記載されているシンタックスの一部に,関数に渡されている引数の形が <arg-spec>
で指定された形状になっていないものがあることに気づきました.そこで,TeXConf 2017終了後にこうしたミスを自動的に検出する Python3 スクリプトを書いたところ,23箇所で同様の間違いがあることを発見しました.
こうして発見した誤植をすべて修正して LaTeX3 の GitHub リポジトリに pull request を出してみたところ,無事マージされました.これで私も晴れて LaTeX3 コントリビュータになりました.めでたし,めでたし.
-
この76関数のリストは https://wtsnjp.com/others/expl3-wargs.txt に置いてあります. ↩︎
-
ちなみに
\cs:w
の引数終了位置を表すデリミタは\cs_end:
です. ↩︎ -
質疑応答の時間中に黒木さんにご指摘頂いたように,現時点でも数式中の「上付き文字」や「下付き文字」を表現するために
^
や_
ではなく,何らかのマクロを利用している TeX ユーザは存在します. ↩︎