本文中の「ぺ」をすべて「ぺりを」に変えたい
本文中の「ぺ」を全部「ぺりを」にしたくなることはありませんか?誰しも一度はあると思います. 今回はこれを実装しようと思います.
\periwoと\endperiwoで挟まれた部分に対してそのような処理をしたいとします.
方針1
\@tforを使う:一文字一文字が「ぺ」かどうかを判定すればよい. 入力する文字列が長すぎると困ったりするのかな, よくわからないけど今回は@tforの話をしたいわけではないので今後の課題ということで……
方針2
今回はこっちがメインです. \periwo の直後のトークンXが「ぺ」かどうかを判定し, そうならば「ぺりを\periwo」, 異なれば「X\periwo」を返す, という方針で書きたいとします. この方針そのままだと別の制御綴を挟むとヤバいですが, 今回はただの文字列に対して動くことを目標として, 一旦見逃すことにします.
さて, 上の方針は次が可能であるためできそうです:
\def\testa#1{#1が先に来て\testb}
\def\testb#1{#1が後に来る}
入力:testa ぺり
出力:ぺが先に来てりが後に来る
\defはあくまで{}内の置き換えにすぎず, 中身の展開はしないことがポイントです.
となると次のようにしたくなります.
\def\periwo#1{%
\def\karia{#1}%
\def\PE{ぺ}%
\ifx\karia\PE
ぺりを\periwo
\else
#1\periwo
\fi
}
\def\endperiwo#1{}
こうすると, 例えば
\periwo っぺの法則\endperiwo
は順に
・っ\periwo ぺの法則\endperiwo
・っぺりを\periwo の法則\endperiwo
・っぺりをの\periwo 法則\endperiwo
・っぺりをの法\periwo 則\endperiwo
・っぺりをの法則\periwo \endperiwo
・っぺりをの法則\endperiwo\periwo
・っぺりをの法則
と展開されそうです. しかし, 実行してみると永久に出力が得られません. なぜか.
それは, \ifx文中の\periwoが次の制御綴\elseや\fiを引数として読んでしまい無限ループに入るためです. そのため, この展開を制御するために例えば
\def\periwo#1{%
\def\karia{#1}%
\def\PE{ぺ}%
\ifx\karia\PE
\def\karib{ぺりを\periwo}%
\else
\def\karib{#1\periwo}%
\fi
\karib
}
とか
\def\periwo#1{%
\def\karia{#1}%
\def\PE{ぺ}%
\ifx\karia\PE
\def\karib{ぺりを}%
\else
\def\karib{#1}%
\fi
\karib\periwo
}
とか
\def\periwo#1{%
\def\karia{#1}%
\def\PE{ぺ}%
\ifx\karia\PE
ぺりを%
\else
#1%
\fi
\periwo
}
とかするなりの方法を取ることでうまく行きます.
でもこれは人工的なのでもっと直接的に制御したいです. そこで次のことを考えました:\periwoより前に\elseや\fiをTeXが読めたら良いのでは?つまり,
\def\periwo#1{%
\def\karia{#1}%
\def\PE{ぺ}%
\ifx\karia\PE
ぺりを\expandafter\periwo
\else
#1\expandafter\periwo
\fi
}
とすれば動くのではないか?……
しかし, いざこれを実行してみるとバグります. これはいったい何が起きているのでしょうか. そもそも\elseや\fiを「展開する」とはどういうことなのでしょうか. それがわかったとして, もし\fiを先に展開してしまったら「\periwo」は読まれることになるのでしょうか. もっと言えば\expandafterは先に進んだ後に「戻る」ということをしていますがこれは何なのでしょうか.
また根本的な部分で知識が抜けているのかもしれません. 現在のぺりをには理解しかねました……
ぺりをだねぇ
3/7追記:最後の例は\endperiwoの定義を\def\endperiwo#1#2{}にするだけで解決しました. \def\endperiwo#1{}だと, 最後の\endperiwoの引数が\expandafterになって\periwoが余るというオチで, ただの初歩的なミスでした……