Re: mathchoice と settoheight

名前: トノ
日時: 2002-08-24 14:56:26
IPアドレス: 202.219.231.*

>>10373 北見さんに 》 思いつきませんでした。 なんてコメントいただくと、鼻が高いです。 気をよくしたところで、あらためて斉藤さんのソースについて、 考察してみたいと思います。 まず問題になるのは、\mathchoice の引数はそれぞれ暗黙のうちにグルーピング されて実行されるということです。例えば次のソースのように、\settoheight を使わない単純な代入で実験してみると、「1.0pt」と画面に出力されるます。 \makeatletter $ \@tempdima=1pt \mathchoice{\@tempdima=2pt }{\@tempdima=3pt }{\@tempdima=4pt }{\@tempdima=5pt } \typeout{\the\@tempdima}% $ このグルーピングについて、手許の解説書の類で確かめようとしたのですが、明 確に書かれているものは見あたりませんでした。唯一 TeXbook に、 「\mathchoice の各引数はサブ数式として組立てられる」という趣旨の記述があ ります。サブ数式というのは、通常その内部が一つのグループになるものなので、 これが、\mathchoice の実行前に代入した値が残ってしまう原因だと思われます。 さて、グルーピングのために \mathchoice の外で参照することが出来ないとい うことであれば、グローバルな代入をすればいいというのが定石です。そこで、 \makeatletter $ \global\dimen@ii=1pt \mathchoice{}{\global\dimen@ii=3pt }{}{} \typeout{\the\dimen@ii} $ とすると、画面には「3.0pt」と表示され、代入そのものは期待どおりにグロー バルに行なわれていることが確認できますが、 \makeatletter $ \global\dimen@i=1pt \mathchoice {\global\dimen@i=2pt } {\global\dimen@i=3pt } {\global\dimen@i=4pt } {\global\dimen@i=5pt } \typeout{\the\dimen@i} $ とすると、画面には「5.0pt」と表示されます。\mathchoice の前に \displaystyle、\textstyle、\scriptstyle、\scriptscriptstyle を置いてみて も、画面出力は変わりません。つまり、常に \scriptscriptstyle での代入結果 が得られてしまいます。これについては角藤先生が既に <ahref="10353.html">#10353</a> で書いて おられるように、\mathchoice は、全ての引数をそれぞれ一旦タイプセットして しまうため、最後に行なわれたグローバルな代入(\scriptscriptstyle での実 行結果)の結果しか参照することが出来ないのだと思われます。 私が #10371 で書いたものは、\write を使うことで、\mathchoice の 引数のうちの採用されたものだけについて、値を取り出そうというものです。 \write は、外部ファイルへの書込みを行なう命令ですが、\write が現れた時点 では実際の書込みが行なわれず、その部分がページとして dvi ファイルに出力 される時点で書込まれるという特徴があります。\mathchoice の選択肢が 4 つ とも実行されるにしても、最終的に選択されたもの以外はページに出力されませ んので、そこに書かれた \write も実行されることがないという理屈です。タイ プセット時に測った高さを aux ファイルに記録しておき、次のタイプセット時 に aux ファイルから読込んだ値を \useheight で使うようになっています。 \saveheight で指定するラベルに重複がないかチェックしていない、前回記録し た値から変更がないかチェックしていない、\saveheight されていないラベルに 対して \useheight しても黙って 0pt という値を返している、といった問題点 がありますので、常用するにはもう少し煮詰めた方がいいでしょう。また、 \useheight で使う値が、常に直前の \saveheight のものだと決まっているなら、 カウンターと併用するなどして、ラベルを一々指定しなくてもいいようにするこ とも出来ると思います。

この書き込みへの返事:

お名前
題名 
メッセージ(タグは <a href="...">...</a> だけ使えます)