[tex-eplain] Treat \refn as a number?

geolsoft at mail.ru geolsoft at mail.ru
Tue Aug 17 19:37:14 CEST 2004


On Sat, Aug 14, 2004 at 03:05:05PM +0200, Rodolfo Medina wrote:
> The solution you suggested seems to work perfectly
> (although the \IsInteger macro remains totally misterious to me!).



I thought you might be interested in understanding how \IsInteger works---
it's quite amusing (well, if you are into such things).

  \def\gobbleminus#1{\ifx-#1\else#1\fi}

\gobbleminus helper does what its name suggests---it gobbles a minus, if it is
present.  If parameter #1 starts with a minus, that minus gets compared by \ifx
with `-'.  As this will hold true, \ifx...\fi will expand to the rest of #1
(without the minus sign, it has been `gobbled' by \ifx in comparing).  If
parameter #1 did not start with a minus, then the \ifx will fail, returning the
full #1 (from between \else and \fi).

  \def\IsInteger#1{%
    TT\fi
    \ifcat_\ifnum9<1\gobbleminus#1 _\else A\fi
  }

The most mysterious at first glance may seem the two T's followed by \fi, but
all they do is cancel out \if preceding the call to \IsInteger.  Remember, we
call \IsInteger like this:

  \if\IsInteger{<subject of test>}%
    <deal with integer>%
  \else
    <deal with non-integer>%
  \fi

We will substitute our own \if (\ifcat, to be precise) to match up with \fi to
come after \IsInteger.

Now the fun part.  Let's see what the following construction

  \ifnum9<1\gobbleminus#1 _\else A\fi

expands to in different situations.

1. Parameter #1 is a number.  The number which started with `1' after `<' will
   end only after the end of #1 (with `-' stripped from #1 by \gobbleminus).
   Since #1 is a number, it appends some digits to 1 thus making it greater than
   9; \ifnum holds true, and the construction expands to an `_'.

2. Parameter #1 is not a number.  We have two possibilities:

   2.a. #1 does not even start with a number.  The number started with `1' after
        `<' will end right after this `1', and \ifnum will fail since 9 is less
        than 1; the construction expands to A;

   2.b. #1 starts with a number, followed by something else.  \ifnum will hold
        true, but the construction expands to that `something else' followed by
        an `_'.

Now it is easy to understand when we get a true and when a false from \ifcat_...

In case 1, we get a true, so the true-part (<deal with integer>) gets expanded
in \if\IsInteger construction.

In case 2.a, we get a false (unless `A' is active and is an alias for `_', or
vice versa, which sure is weird).

In case 2.b, outcome depends on what `something else' starts with.  If it does
NOT start with an `_', we are alright and get a false.  We are out of luck if it
does start with an `_':  we get a true, and the rest of `something else'
followed by an `_' gets out into the output.

Yet another flaw of \IsInteger, as I mentioned before, is that \IsInteger{ {12}}
will give us a true since we pass `{12}' on to gobbleminus as a single parameter
`12'.  In older issue of The UK TeX FAQ http://www.tex.ac.uk/faq (at least in
the one dated 2003-02-06) this issue was `solved' by the following definitions:

  \def\gobble#1{}
  \def\gobbleminus{\futurelet\temp\gobm}
  \def\gobm{\ifx-\temp\expandafter\gobble\fi}

but don't believe them---\futurelet gets in the way of the number in \IsInteger
(the one we started with `1' after `<'), so that number will always end right
after the `1' upon encountering \futurelet, causing \IsInteger to always fail.
Too bad, if this worked it would make \IsInteger more robust.


Good luck,
Oleg Katsitadze



More information about the tex-eplain mailing list