20

I have seen packages using

\def\afterelse#1\else#2\fi{\fi#1}

which TeX seems happy to accept. But on taking the first branch, isn't TeX expecting \else instead of \fi? That is, isn't the following the correct syntax for the first fork? This too is accepted by TeX.

\def\afterelse#1\else#2\fi{\else#1}

EDIT

Thanks to Egreg. Tracing \ifs shows what is happening.

\def\loggingallstuff{%
  \tracinggroups\@ne\tracingifs\@ne\loggingall\tracingassigns\@ne
}

\def\afterelse#1\else#2\fi{\fi#1}

{\loggingallstuff
  %\edef\x{\iftrue\afterelse T\else F\fi}
  \edef\x{\iftrue T\else F\fi}
%  \edef\x{\iffalse T\else F\fi}
}

% \iftrue
{\edef}
{\iftrue: (level 1) entered on line 23}
{true}
{\else: \iftrue (level 1) entered on line 23}
{\fi: \iftrue (level 1) entered on line 23}
{changing \x=undefined}
{into \x=macro:->T}

% \iffalse:
{\edef}
{\iffalse: (level 1) entered on line 24}
{false}
{\else: \iffalse (level 1) entered on line 24}
{\fi: \iffalse (level 1) entered on line 24}
{changing \x=undefined}
{into \x=macro:->F}

Here is one case I find interesting:

\documentclass{article}
\usepackage{pgfkeys}
\makeatletter

\def\pgfkeysafterfi#1\fi{\fi#1}
%\def\pgfkeysafterelsei#1\else#2\fi{\fi#1}
\def\pgfkeysafterelsei#1\else#2\fi{\else#1} % wrong but gives no error.

\def\pgfkeysifkeydef#1#2#3{%
  \ifcsname pgfk@#1/.@cmd\endcsname
    \pgfkeysafterelsei{#2}\else\pgfkeysafterfi{#3}\fi
}
\pgfkeys{%
  /handlers/.if definable/.code 2 args={
    \pgfkeysifkeydef{\pgfkeyscurrentpath}{%
      \@latexerr{Oops, key '\pgfkeyscurrentpath' already exists}
        {You aren't in trouble here!}%
    }{%
      \pgfkeys{\pgfkeyscurrentpath/.default=#1,\pgfkeyscurrentpath/.code=#2}%
    }%
  }%
}
\pgfkeys{
  /fam/.is family,/fam/.cd,
  keya/.if definable=\relax\@empty,
  keya/.if definable=\@empty{\def\x##1{##1*#1}},
}
\makeatother
\begin{document}
x
\end{document}
3
  • 1
    Another odd point with conditionals is that \iftrue\else\or\fi is legal and writes {\or: \iftrue (level 1) ...} to the log when tracing ifs. Aug 25, 2012 at 7:57
  • @BrunoLeFloch: But does it have any application? \iffalse\def\x{T}\else\def\x{F}\or\fi gives extra \or.
    – Ahmed Musa
    Aug 28, 2012 at 2:15
  • I can't think of an application right now, but there may be weird cases where it is useful. Say that you have a macro \def\foo#1{\ifx?#1abc\else def\fi} (meant to give abc when #1 is ? and def otherwise). Giving it ?\else as an argument will produce no output. I've had somewhat similar situations within l3fp. Aug 28, 2012 at 11:10

1 Answer 1

20

Let's use \iftrue and \iffalse for testing what happens, assuming the definition

\def\afterelse#1\else#2\fi{\fi#1}

\iftrue

\iftrue\afterelse T\else F\fi

becomes

\afterelse T\else F\fi

and the next expansion gives

\fi T

\iffalse

\iffalse\afterelse T\else F\fi

becomes

F\fi

and the expansion of \fi is empty.


The important thing is that when the "true" branch is taken, only the test is removed, while everything up to and including \else is removed when the "false" branch is taken. This can be seen in the following interactive session:

This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax

*\toks0=\expandafter{\iftrue T\else F\fi}         

*\showthe\toks0
> T\else F\fi .
<*> \showthe\toks0

? 

*\toks0=\expandafter{\iffalse T\else F\fi}

*\showthe\toks0
> F\fi .
<*> \showthe\toks0

The code

\def\afterelse#1\else#2\fi{\else#1}

is not correct, as shown by the following interactive session

This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax

*\def\afterelse#1\else#2\fi{\else#1}

*\iftrue\afterelse T\else F\fi

*
(Please type a command or say `\end')
*\bye
! Incomplete \iftrue; all text was ignored after line 0.
<inserted text> 
                \fi 
<to be read again> 
                   \bye 
<*> \bye
2
  • 1
    So if I understand it correctly, when TeX sees \else, it removes everything up to the corresponding \fi?
    – yo'
    Aug 24, 2012 at 22:10
  • @tohecz Yes, that's the effect of the expansion of \else.
    – egreg
    Aug 24, 2012 at 22:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .