2017年2月11日

同じくjlreq.clsに次のようなマクロがある.

\jlreq@ifempty{<トークン列>}{<実行1>}{<実行2>}

これは<トークン列>が空ならば<実行1>を,そうでなければ<実行2>になる.e-TeX拡張が使える場合(jlreq.clsはこれを仮定している)は,このマクロの定義は

\long\def\jlreq@ifempty#1{%
  \expandafter\ifx\expandafter\relax\detokenize{#1}\relax
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
とするのが最善手だ.

としてもおもしろくないので,ここでは通常のTeXで考えてみる.よく見るのが

\def\jlreq@ifempty{%
  \ifx\jlreq@uniqtoken#1\jlreq@uniqtoken
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
だけど(かなり長いことこれにしていた)これはやっぱり\jlreq@ifempty{\iftrue\fi}で破綻する.というかした.

ともかく「最初のトークンだけ取り出す」マクロが作れればよいので,昨日のを少し応用して

\def\A#1#{\B#1\Y\Z}
\def\B#1#2\Z#3\Z{#1}
というマクロを考えて,\A#1\X{}\Zという形のマクロを考えてみる,これを二回展開すると次のようになる.#1における{***}の前までをS,その後をTとすると,
  • Tが空でないならば,\A ST\X{}\Z\B S\Y\Z T\X{}\ZS\Yの先頭
  • Tが空ならば,\A S\X{}\Z\B S\X\Y\Z{}\ZS\X\Yの先頭
となる.言い方を変えると,#1の先頭トークンが得られていることになる.ただし先頭が{の場合は\Yが,また#1が空の場合は\Xに展開される.

これを使って(マクロ名を変更して)次のようにしてみた.

\def\jlreq@getfirsttoken#1#{\jlreq@getfirsttoken@#1\bgroup\jlreq@endmark}
\def\jlreq@getfirsttoken@#1#2\jlreq@endmark#3\jlreq@endmark{#1}
\long\def\jlreq@ifempty#1{%
  \expandafter\expandafter\expandafter\ifx\jlreq@getfirsttoken#1\jlreq@uniqtoken{}\jlreq@endmark
  \jlreq@uniqtoken
   \expandafter\@firstoftwo
  \else
   \expandafter\@secondoftwo\fi}
前のと対応させると,\X\jlreq@uniqtoken\Y\bgroup\Z\jlreq@endmarkである.これで大体うまく行くと思う.まぁ空白トークンは闇に消えますが.

2 件のコメント:

  1. etoolboxに \ifblank というマクロがありますが、それと同じ仕様ですかね。

    %---- etoolbox.sty 470行目
    % ここで'&'のcatcodeは3で, 実質的にユニーク
    \newcommand{\ifblank}[1]{% from url.sty
    \etb@ifblank@i#1&&\@secondoftwo\@firstoftwo:}
    \long\def\etb@ifblank@i#1#2&#3#4#5:{#4}

    返信削除
  2. なんかそうっぽいですね.賢いなぁ.(そして\expandafterを消された.)そうすると\jlreq@ifendmarkもこんなんでいいのか.
    \def\jlreq@ifendmark#1{\jlreq@ifendmark@#1\jlreq@endmark\@firstoftwo\@secondoftwo:}
    \def\jlreq@ifendmark@#1\jlreq@endmark#2#3#4:{#3}

    ちなみに手元のetoolbox(2017/01/02)の\ifblankは\detokenizeを使った実装になっているんですが,上のだと何かまずい点があったんでしょうか?

    返信削除

コメントの追加にはサードパーティーCookieの許可が必要です