TeX言語における「if not」的条件分岐

TeX言語における「if not」的条件分岐

- Ryuta Kudo の投稿
返信数: 9
\newif\if@hoge

としたうえで、これが「偽」のときのみ何らかの処理を行う、つまり

\if@hoge
    (何もしない)
\else
    (何らかの処理)
    (何らかの処理)
    (何らかの処理)
    ...
\fi

のような条件分岐を行いたいのですが、これはどう記述するのが正解、もしくは安全でしょうか。

特に(何もしない)をどうすべきかが気になります。

\if@hoge\else
    (何らかの処理)
    (何らかの処理)
    (何らかの処理)
    ...
\fi

としてしまって構わないのでしょうか。それとも、より適切な記述があるのでしょうか。

※説明のため簡略化しましたが、@hogeは他の場所でも条件分岐で利用することを想定しており,\newif\if@nothogeのようにし、\if@nothoge ... \fiとする、というのは本件の意図ではありません。

是非ともご教示お願いいたします。

Ryuta Kudo への返信

Re: TeX言語における「if not」的条件分岐

- 北見 けん の投稿
\if@hoge\else で良いと思いますが、
何か意図通りに動かなかった事例がありましたか?
北見 けん への返信

Re: TeX言語における「if not」的条件分岐

- Ryuta Kudo の投稿

北見さん

返信ありがとうございます。

> 何か意図通りに動かなかった事例がありましたか?

そういったわけではありません。誤解を招いてしまい申し訳ございません。

別の回答者様への返信でも記載させていただいたのですが、色々なパッケージのソースを見ながら勉強していた際、私の貧相な知識では「この位置で?」と思ってしまうような箇所(当然必要だから、そこに入れているのだと想像しますが)で\relaxを差し込んでいることを何度か見かけたことがありました。

そのため、今回の件も、もしかしたら

\if@hoge
    \relax
\else
    (処理)
\fi

とする方が良いのではないかと疑問に思ったものの、TeX言語は無知故、自力で判断できず、そこで、詳しい方にご教示いただければと思って質問させていただいた次第です。

Ryuta Kudo への返信

Re: TeX言語における「if not」的条件分岐

- ut の投稿
# 北見さんのおっしゃる通りだと思いますので、以下は飽くまでご参考までです。

# 何か具体例をお示しできれば良かったのですが、思い付かないので、手元の
# 文献からのコピペばかりです。

以前のご投稿で、『独習』をお持ちだとおっしゃっていましたが、同書には、
以下のようにありますね:

------------------------------------------------------------
吉永徹美『独習LaTeX2e』(翔泳社・2008年)502頁

11.1.1 条件処理の一般形

〈if-test〉〈condition〉〈true-case〉\else〈false-case〉\fi

・ ……
・〈true-case〉は条件(〈condition〉)が真である場合に実行される処理です
(空であってもかまいません)。
・ ……
------------------------------------------------------------

ちゃんと「空であってもかまいません」と説明されています。

確かに、The TeXbook だと、207 ページに:
  If the〈false text〉is empty, you can omit the \else.
としか書かれてないので、〈true text〉のほうは省略してもいいのかどうか、
迷われるかも知れません。

でも、TeX の入門書や解説書ですと、『独習』同様、〈false text〉も
〈true text〉も省略可能ということに触れているものが多いような気がします。

私の手元にあるものから、conditionals の部分の説明を抜粋してみますと:

------------------------------------------------------------
Victor Eijkhout, TeX by Topic, 1991--2004 (Electronic Version 1.1)
13.1 The shape of conditionals

Conditionals in TeX have one of the following two forms
  \if...〈test tokens〉〈true text〉\fi
  \if...〈test tokens〉〈true text〉\else〈false text〉\fi
where the〈test tokens〉are zero or more tokens, depending on the particular
conditional; the〈true text〉is a series of tokens to be processed
if the test turns out true, and the〈false text〉is a series of tokens
to be processed if the test turns out false. Both the〈true text〉and
the〈false text〉can be empty.

------------------------------------------------------------
Raymond Seroul, Silvio Levy, A Beginner's Book of TeX, 1991, p. 184

In almost all cases the construction is the same:
  test text1 \else text2 \fi
Either text1 or text2 can be empty (or even both, but then there isn't
much point to the conditional). If text2 is empty, the \else is not necessary.

------------------------------------------------------------
Stephan von Bechtolsheim, TeX in Practice, Vol. III, 1993, pp. 317 f.

5. It is perfectly legal to have no〈true text〉, that is no instructions
between the conditional and the \else.

6. It is also perfectly legal to have no〈false text〉, in which case
the \else is usually (but not necessarily) omitted. ...

------------------------------------------------------------
David Salomon, The Advanced TeXbook, 1995, p. 142

... they all have the same format, namely, "\if〈test〉then part \else
else part \fi", where〈test〉is different for each type of \if, and
either the "then part" or the "\else else part" is optional. Thus it is okay
to write conditionals such as "\if〈test〉then part \fi" or
"\if〈test〉\else else part \fi", but the \fi must always appear.

------------------------------------------------------------

ちなみに、e-TeX で追加された \unless というのを前置すると、真のときの
処理と偽のときの処理とを逆にすることができます:

\documentclass{jarticle}
\begin{document}

\newif\ifabc
\abctrue

(1)
\ifabc
  abc
\else
  xyz
\fi

(2)
\ifabc
\else
  xyz
\fi

(3)
\unless\ifabc
  abc
\else
  xyz
\fi

(4)
\abcfalse
\unless\ifabc
  abc
\fi

\end{document}
ut への返信

Re: TeX言語における「if not」的条件分岐

- Ryuta Kudo の投稿

utさん

丁寧な回答をありがとうございます。

色々なパッケージのソースを見ながら勉強していましたが、ときどき私の知識では「この位置で?」と思ってしまう箇所(当然必要だから入れているのでしょうが)で\relaxを差し込んでいることを何度か目にしたことがあり、今回も

\if@hoge
    \relax
\else
    (処理)
\fi

とする方が良いのか疑問に思いました。

TeX言語は無知故、自力では判断できず、詳しい方にご教示いただければと思って質問させていただいた次第です。

特段、\relaxする必要はなく、\if@hoge\else ... \fiとして構わないようですね。


さて、

> 以前のご投稿で、『独習』をお持ちだとおっしゃっていましたが、同書には、 以下のようにありますね:

確かに手元の『独習LaTeX2e』の502ページを見てみますと記載がありました。 完全に見落としておりました。お恥ずかしい限りです。

海外の文献の情報もありがとうございます。

\unlessというものもあるのですね。たいへん勉強になります。


ちなみに、今回の質問にあるような処理を行う場合、utさんであればどう記述なさいますか?

\elseで処理するか、はたまた\unlessを前置して処理するか、はたまた別の記述とするかなど、簡潔で構いませんので、ご見解を伺えると幸いです。

Ryuta Kudo への返信

Re: TeX言語における「if not」的条件分岐

- ut の投稿
おはようございます。

> 今回も
>
> \if@hoge
>    \relax
> \else
>    (処理)
> \fi
>
> とする方が良いのか疑問に思いました。

あー、なるほど、そういうことでしたか。

> \elseで処理するか、はたまた\unlessを前置して処理するか、はたまた別の記述とするか

普通に〈true text〉を空にするか、それとも \unless を使うかに
ついては、多分、あまり違いはないのだと思われます(\unless は
単純に真偽の処理を入れ替えるためというよりは、\loop とかと組
み合わせて使うことが多いみたいです)。

あとは、LaTeX のユーザーコマンドの範囲内でということであれば、
ifthen パッケージを使う、というのが模範的な回答でしょうか。

> 海外の文献の情報もありがとうございます。

\if ... \fi というのは LaTeX ではなくて TeX の話になるのです
けれど、日本語での TeX の解説書というのが手元にないので、英語
の文献から引用しました。

私の場合、TeX のプリミティブについて知りたいときに一番最初に
チェックするのは TeX for the Impatient なのですが、今回の場合
はピッタリの記述がなかったので、他の本から探してみました。

最後に、元々のご疑問である、

> ときどき私の知識では「この位置で?」と思ってしまう箇所(当然
> 必要だから入れているのでしょうが)で\relaxを差し込んでいるこ
> とを何度か目にしたことがあり、

についてですが、具体的な例を挙げていただければお詳しい方が
答えてくださると思いますけれど、私が今パっと思い付く \relax
のよく見る使い方というと:

(1)TeX が数値を探し続けるのをやめさせたい場合

(2)TeX が [ ] をオプション引数と誤解するのを防ぎたい場合

とかですかね。

(1)については、例えば The TeXbook の 208 ページに関連する説明
がありますが、そこに書かれていますように:

  \ifnum\balance=0 \fullypaid \else ...

とすべきところを:

  \ifnum\balance=0\fullypaid \else ...

としてしまうと、もしも \fullpaid の展開結果が数値になるような
場合には、\balance と比較される値は 0 ではなくて、0 と \fullpaid
の展開結果とを結合したものになってしまいます。
(おー、そうなると〈true text〉が空になりますね)

そのため、ここでは \balance と 0 とを比較したいのであって、TeX
がそれ以上数値を探し続けるのをやめさせたいのであれば、この場合、
0 の後ろにスペースが必要となるのですが、このスペースを入れる代
わりに \balance=0\relax とすることも多いんじゃないかと思います。
(同様の理由で、カウンタへの数値の代入なんかの場合も、値の後ろ
や、値に展開されるマクロの後ろに \relax をよく置きます)

(2)については、例えば、段落内強制改行や表内の改行のための
\\ ですとか、list 環境で使われる \item とかは、その後ろに [ ]
でオプション引数を取ることができますよね。そのため、\\ で改行
した次の行の最初が [ ] だったり、\item の次に [ ] が来たりす
ると、それらはオプションとして受け取られてしまうので、それを
避けるために \\ の後ろや \item の後ろに \relax を入れること
があります。

(簡単な英語くらいなら読めなくもないですが、コードは読めない
私みたいな者が知ったかぶりをするのは滑稽なことだと自覚はしつ
つも、まずは以上、思い付くままです)
ut への返信

Re: TeX言語における「if not」的条件分岐

- 北見 けん の投稿
utさんがお書きになったもののほかに、\relax を入れておく例としては、
\macro#1{...\if#1\relax...}のような感じで、マクロ引数の直後などでしょうか。コードを書いた時点では確定しないので、展開を止めたくなることもあるでしょう。
\if 等の中ということに限らなければ、\macro{\relax...} のようなマクロ内の先頭に置かれるのも同じ理由です。マクロの直前がどんな様子だったのかがあらかじめわからない場合ですね。
北見 けん への返信

Re: TeX言語における「if not」的条件分岐

- Ryuta Kudo の投稿

北見さん

ご回答ありがとうございます。

> \macro#1{...\if#1\relax...}のような感じで、マクロ引数の直後などでしょうか。

まさにそのような使われ方でした。 ご教示感謝いたします。

ut への返信

Re: TeX言語における「if not」的条件分岐

- ut の投稿
# TeX とは無関係な訂正と、一応 TeX に関係する修正です:

今朝の投稿の "fullpaid" は "fullypaid" の間違いでした、すいません。
(「簡単な英語くらいなら読めなくもない」なんて言っておきながら、
恥ずかし過ぎる間違いです… orz)

あと、「…の後ろや、値に展開されるマクロの後ろに \relax をよく置
きます」とも書いてしまいましたが、後者の場合には、マクロの置換
テキストの末尾に \relax を入れておくのが普通でした…。

例えば、読んでくださったという過日私が書いたペーパー(12/4)に:

  \newcommand{\tempeuler}{... \mathcode`\)="52A9 }

というのが出てきますが、これも実は手元で試してみたときには:

  \newcommand{\tempeuler}{... \mathcode`\)="52A9\relax}

としていました。
(ペーパーは 2 段組みにしたせいで行幅が足りなくなってしまったので、
それで \relax の代わりにスペースに書き替えたのでした)
ut への返信

Re: TeX言語における「if not」的条件分岐

- Ryuta Kudo の投稿

utさん

丁寧なご回答ありがとうございます。たいへん勉強になります。

特に

(2)TeX が [ ] をオプション引数と誤解するのを防ぎたい場合

の使い方は目から鱗が落ちました。

ありがとうございました。