講演『expl3入門』の補足

2017-10-29 (updated: 2025-12-09) #expl3

もう2週間ほど前のことになりますが、10月14日(土)に開催されたTeXConf 2017に参加してきました。私は一般講演枠を1つ頂いていて『expl3入門』というタイトルで、その名の通りexpl3という言語のチュートリアル講演を行いました。その際の発表資料がこちらです。

そもそも一般講演を申し込んだ理由が「講演という“締め切り”を設定することで、自分がexpl3の勉強をしたいから」というところにあったこともあり(発表駆動)、かなり直前になってドタバタと突貫で準備を行ったわけですが、幸いにもご好評を頂くことができました。

そして発表後の質疑応答では6つほどの質問を頂戴しました。しかし、時間の関係と私の知識不足により、その場では最低限度の回答しかできなかったものもありました。そこで、本稿では頂いた質問に再度答えるQ&Aの形をとって、少し詳細な補足をしてみようと思います。

Warning

質疑応答の時間中にメモをとっていたわけではないので、実際に頂いた質問とは少し表現や論点が異なる可能性があります。また、質問の順番は恣意的に入れ替えています。予めご了承ください。

Q1. 引数指定子wの使用例は\exp_after:wN以外にもあるか?

はい、あります。

その場では具体的な例を挙げることはできませんでしたが、expl3の公式ドキュメント(interface3.pdf)には内部関数も合わせて少なくとも76個<arg-spec>wを含む関数が掲載されています1

引数指定子wはexpl3の文法上「例外」とされる引数形状を表すもので、具体的には

  1. un-balancedを許容する1トークン
  2. 特定のトークン(デリミタ)までのトークン列
  3. TeX式の条件分岐

などを含みます。

TeX言語の\expandafterが代入されたexpl3の関数\exp_after:wNはこのうち1つ目に該当します。

2つ目のケースには、TeX言語の\csnameにあたる\cs:wなどが含まれます2

expl3では基本的に引数指定子TFを含むより高級な条件分岐関数の使用が好まれますが、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コントリビュータになりました。めでたし、めでたし。


  1. この76関数のリストはhttps://wtsnjp.com/others/expl3-wargs.txtに置いてあります。 ↩︎

  2. ちなみに\cs:wの引数終了位置を表すデリミタは\cs_end:です。 ↩︎

  3. 質疑応答の時間中に黒木さんにご指摘頂いたように、現時点でも数式中の「上付き文字」や「下付き文字」を表現するために^_ではなく、何らかのマクロを利用しているTeXユーザは存在します。 ↩︎