System Macros/Branches and Decisions

From Wiki
< System Macros
Revision as of 09:22, 1 August 2006 by Taco (talk | contribs) (split off section)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

System_Macros

When Pragma ADE started using TeX in the late eighties, their first experiences with programming concerned a simple shell around LaTeX. The commands probably used most at Pragma ADE are the itemizing ones. One of those initial shell commands took care of an optional argument, that enabled the specification of the item symbol to be sued. Without understanding anything they were able to locate a LaTeX macro that could be used to inspect the next character.

It is that macro that the ancester of the next one presented here. It executes one of two actions, dependant of the next character. Disturbing spaces and line endings, which are normally interpreted as spaces too, are skipped.

\doifnextcharelse {char} {then ...} {else ...}

The standard way of testing if a macro is defined is comparing its meaning with another undefined one, aptly named \undefined. To garantee correct working of this set of macros, \undefined may never be defined by a user!

\doifundefined      {string}    {...}
\doifdefined        {string}    {...}
\doifundefinedelse  {string}    {then ...} {else ...}
\doifdefinedelse    {string}    {then ...} {else ...}
\doifalldefinedelse {commalist} {then ...} {else ...}

Programming in TeX differs from programming in procedural languages like Modula. This means that one --- well, let me speek for myself --- tries to do the things in the well known way. Therefore the next set of \ifthenelse commands were between the first ones we needed. A few years later, the opposite became true: when programming in Modula, I sometimes miss handy things like grouping, runtime redefinition, expansion etc. While Modula taught me to structure, TeX taught me to think recursive.

\doif     {string1} {string2} {...}
\doifnot  {string1} {string2} {...}
\doifelse {string1} {string2} {then ...}{else ...}

These macros test string equality of the (expanded) first two arguments.

We complete our set of conditionals with:

\doifempty     {string} {...}
\doifnotempty  {string} {...}
\doifemptyelse {string} {then ...} {else ...}

This time, the string is not expanded. Remember to expand it yourself where needed.

We can check if a string is present in a comma separated set of strings. Depending on the result, some action is taken.

\doifinset     {string} {string,...} {...}
\doifnotinset  {string} {string,...} {...}
\doifinsetelse {string} {string,...} {then ...} {else ...}

The second argument is the comma separated set of strings. If the first string expands 'empty', it is considered to be always in the set. The comma separated set is not expanded.

Probably the most time consuming tests are those that test for overlap in sets of strings.

\doifcommon     {string,...} {string,...} {...}
\doifnotcommon  {string,...} {string,...} {...}
\doifcommonelse {string,...} {string,...} {then ...} {else ...}

%%\doifinstringelse %%\doifincsnameelse

We can check for the presence of a substring in a given sequence of characters.

\doifinstringelse {substring} {string} {then ...} {else ...}

The next alternative proved to be upto twice as fast on tasks like checking reserved words in pretty verbatim typesetting. This is mainly due to the fact that passing (expanded) strings is much slower that passing a macro.

\doifincsnameelse {substring} {\string} {then ...} {else ...}

Where \doifinstringelse does as much expansion as possible, the latter alternative does minimal (one level) expansion.

The next macro executes a command depending of the outcome of a test on numerals.

\doifnumberelse {string} {then ...} {else ...}

The macro accepts 123, abc, {}, \anumber and \the\count....

The definition of this macro is extremly ugly, or extremely beautiful, depending on how you feel about TeX macro expansion. It is the first of only a few that will actually appear in this series of articles, I promise.

\long\def\doifnumberelse#1%
  {\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}