29

There have been a few questions about braces recently, specifically about when to use them (see this and that question). Note: I had mistakenly stated that SamB was the author of both questions.

But there are other ways to get token lists that behave like braces. For instance,

{ and 
}

\let\bgroup{ and 
\let\egroup}

\def\Egroup{\iffalse{\fi}} and 
\def\Bgroup{\expandafter{\iffalse}\fi}

\def\bbgroup{\expandafter{\ifnum0=`}\fi} and
\def\eegroup{\ifnum0=`{\fi}}

Of course, this is not a complete list. It would be nice to have a showcase of typical situations where one can/should use each. Share on any brace hack that appears in your macros, or in packages that you've written/read about/used...

I guess one hack per answer.

3
  • An explanation of \alignsafe@testopt in amsmath.sty would be great. (In the dtx they say "Testing for an optional argument can be really, really tricky in certain complicated contexts.") Jan 29, 2011 at 21:28
  • 1
    @Bruno: Can you please explain the \expandafters in \Bgroup and \bbgroup? I don't see what changes if the \expandafters are omitted. Mar 1, 2011 at 14:55
  • @Hendrik: They are needed so that \Bgroup and \bbgroupactually expand to an open brace when hit from the left by expansion. For instance, \expandafter\somemacro\expandafter{\iffalse}\fi will grab the rest of the current brace group. I think that it should be possible to use it for an expandable \afterbracegroup. See my answer below for another use. Mar 1, 2011 at 19:11

5 Answers 5

16

A nice example of using a \iffalse{\fi trick was posted by Dan Luecking on comp.text.tex in the thread Capilatizing the first character with a complete explanation. It's a macro that takes a string as argument and defines a macro \Fcap which contains the same string but with the first letter upper-cased (e.g. test becomes Test):

\documentclass{article}
\def\FirstcapD#1#2\delimiter{%%% Delimited
   \iffalse{\fi
   \uppercase{\edef\Fcap{\iffalse}\fi#1}#2}}%
\begin{document}
\FirstcapD test\delimiter
\ttfamily\meaning\Fcap
\end{document}

shows that \Fcap is macro:->Test i.e. the upper-case version of the argument test. I reproduce here the explanation of how the code works. As the macro is delimited, \FirstcapD test\delimiter will make #1=t and #2=est.

The first \iffalse{\fi is just here to have a balanced number of braces inside the definition of \Firstcap, but as \iffalse is always false, it disappears during expansion.

Then \uppercase{\edef\Fcap{\iffalse}\fi#1} is executed with #1 = t. The \uppercase{\edef\Fcap{\iffalse}\fi t} thus becomes \edef\Fcap{\iffalse}\fi T (the t has been upper-cased).

At this stage, we have \edef\Fcap{\iffalse}\fi Test} because #2 is est. This code is not balanced in braces, but that doesn't matter as \edef expands as it reads. Because \iffalse is always false, the \iffalse}\fi disappears, and what remains is just \edef\Fcap{Test}.

15

I'm going to give a try at Hendrik's suggestion of explaining \alignsafe@testopt. The problem was reported in the LaTeX bug database as amslatex/1834 (it's now fixed) with the follow-up latex/3040. The problem arises in the following situation ({aligned} immediately followed by a & and inside a tabular-like environment):

\documentclass{article}
\usepackage{amsmath}
\makeatletter\let\alignsafe@testopt\@testopt\makeatother % reactivates the bug
\begin{document}
\begin{align}\begin{aligned}
&b=d%% Problem: First nonspace token found by lookahead was "&"
\end{aligned}\end{align}
\end{document}

The reason is that {aligned} looks ahead for an optional argument and this triggers the building of the table cell, causing an error. The fix proposed in the bug report latex/3040 is simpler than what ended up in amsmath.sty:

\def\@testopt#1#2{%
  {\ifnum`}=0\fi
  \@ifnextchar[%
    {\ifnum`{=\z@\fi}#1}%
    {\ifnum`{=\z@\fi}#1[#2]}%
}

but has one drawback: it introduces a spurious {} which could be intrusive in some cases. The idea behind the code is the following: by opening a brace before LaTeX looks ahead for [, the next & will not immediately end the current cell of the parent environment, thus allowing LaTeX to test whether it is equal to [. A similar effect can be seen when comparing

\begin{tabular}{c|c}a\meaning&b\end{tabular}

with

\begin{tabular}{c|c}a{\meaning&}b\end{tabular}

The \ifnum`}=0\fi and \ifnum`{=\z@\fi are only here so that \def doesn't complain that its contents is not balanced in braces. During expansion, they disappear.

The version which ended up in amsmath.sty is more complex as it replaces the explicit { and } of the previous code by \iffalse{\fi and \iffalse}\fi to avoid the drawback mentioned earlier. Here's the code:

\def\alignsafe@testopt#1#2{%
  \relax\iffalse{\fi\ifnum`}=0\fi
  \@ifnextchar[%
    {\let\@let@token\relax \ifnum`{=\z@\fi\iffalse}\fi#1}%
    {\let\@let@token\relax \ifnum`{=\z@\fi\iffalse}\fi#1[#2]}%
}

What is more subtle is that using \ifnum0=`{\fi instead of \iffalse{\fi wouldn't work. This can be illustrated by the fact that

\documentclass{article}
\begin{document}
\begin{tabular}{cc}
a\ifnum`{=0\fi&\ifnum`}=0\fi b\\
\end{tabular}
\end{document}

compiles whereas

\documentclass{article}
\begin{document}
\begin{tabular}{cc}
a\iffalse{\fi&\iffalse}\fi b\\
\end{tabular}
\end{document}

does not. The reason is explained in appendix D (“Dirty Tricks”) of The TeXbook page 385 (see also TeX by Topic, §10.4): when \iffalse{\fi is expanded, it increments the master counter whereas \ifnum0=`{fi does not and it is this master counter which is used for alignment matters (the other counter being the balance counter, which is equally fooled by both). The reason why the expansion of \ifnum0=`{fi doesn't increment the master counter is that there is no explicit brace in it since after \ifnum0= TeX expects a number and so `{ is converted into a number instead of being a backtick followed by a brace (in fact, the real reason why `{ doesn't increase the master counter is that when TeX reads the { after the backtick, it increases the master counter, but when it evaluates `{, it decreases it, so it's as if the counter didn't change). The same would be true for \romannumeral-`{\space but not for \@gobble`{ (because TeX is not in "reading a number" mode after \@gobble).

Here's the table from The TeXbook (page 385) showing what happens to which counter when:

Table of changes to the master and balance counters

14
  • @Philippe: great job! Do you know why there are two different counters? And what would \@gobble`{ do to the counters? Feb 6, 2011 at 15:57
  • @Bruno: Unfortunately, \@gobble`{ globbles the tick so it would act just like a brace. The existence of two counters allows a maximum of flexibility, like hiding things from alignments without creating a group. You can see this with \begin{tabular}{c|c}\relax\iffalse{\fi\def\macro{2}\meaning&\iffalse}\fi\meaning\macro&\\\end{tabular} (the \relax is here to stop the look ahead for \omit; the \meaning& is just here to show that a & can appear without building up a new cell). Feb 6, 2011 at 23:29
  • @Philippe: gobbling the tick was my goal: when expanded, acts like a brace; when passed over, increments the balance counter, but does not change the master counter. Is that right? It would be one way of getting a non-matched brace in a cell. Then I don't know if that's useful. Feb 6, 2011 at 23:59
  • 2
    It would be nice to have some kind of picture showing exactly what happens to which counter when...
    – SamB
    Feb 19, 2011 at 20:54
  • 2
    @SamB: I've added the table from The TeXbook showing what happens to the counters. Feb 25, 2011 at 23:22
9

On the \iffalse{\fi trick again.

Given a list of the form \def\foo{\elt{world}\elt{Hello,}\elt{!}}, I want \popright\foo to remove the last element from \foo (i.e., yield the same as \def\foo{\elt{world}\elt{Hello,}}). It can be done in linear time. The idea is to start with \edef\foo{\iffalse}\fi, and end the definition with \iffalse{\fi}. In between, each element is wrapped in \unexpanded.

\catcode`\@=11
\long\protected\def\popright#1{%
    \edef#1{\iffalse}\fi
    \expandafter\expandafter
    \expandafter\popright@aux
    \expandafter\@gobble #1X}
\long\def\popright@aux#1#2{%
    \ifx X#2%
        \expandafter\popright@end
    \fi
    \unexpanded{\elt{#1}}%
    \popright@aux}
\long\def\popright@end#1\popright@aux{\iffalse{\fi}}
\catcode`\@=12

The last element is detected by noting that it is not followed by \elt, but by X. In the LaTeX3 code, I decided to put something like {?\iffalse{\fi}\@gobblethree} instead of X, and replace the relatively costly \ifx test by \@gobble#2, but that just brings a small speed improvement, and the code is rather more obscure. [see \seq_pop_right:NN in source3.pdf]

Noteworthy is also the fact that D.E.K. himself mentions in the TeXbook (appendix D) that it is probably impossible to do that in TeX. eTeX's \unexpanded is necessary for a full solution.

7

Consider the construction \expandafter\@gobble\expandafter{\iffalse}\fi. First \iffalse}\fi is expanded and disappears. Then \@gobble gobbles everything until it reaches an extra closing brace. A variant of this can maybe be used to implement some form of expandable \aftergroup (which would only work with brace groups). I also use it in the following.

We test whether the first token of a given list of tokens is an explicit begin group character. Note that using \futurelet would not distinguish between an implicit brace \bgroup and an explicit brace {. Also the solution below is expandable.

So, first a LaTeX code using no package. The trick is to hit the argument, #1, with \string. We know that initially, #1 is balanced. If the first token is not a begin group character, then \string#1 is still balanced after one expansion. On the other hand, if the first token is an explicit catcode 1 character, then \string converts it to a harmless catcode, and \string#1 now has an extra end group character (catcode 2).

\makeatletter
\long\def\@thirdoffour#1#2#3#4{#3}

\long\def\iffirst@brace#1{%
  \expandafter\@gobble\expandafter{\expandafter{%
      \string#1*%
    }\expandafter \@thirdoffour \expandafter {\iffalse}\fi
  }\@secondoftwo
}

We make use of this fact using \@gobble, which grabs a brace group and removes it. If the first token was not of catcode 1, then after \string is expanded, the situation looks like

\@gobble{{%
    ...*%
  }\expandafter\@thirdoffour\expandafter{\iffalse}\fi
}\@secondoftwo

\@gobble only leaves \@secondoftwo, which is what we want to grab the false branch coming afterwards. On the other hand, if the first token is a brace group, then the situation looks like

\@gobble{{%
  ...}...*%
}\expandafter\@thirdoffour\expandafter{\iffalse}\fi
}\@secondoftwo

Here, \@gobble leaves

\expandafter\@thirdoffour\expandafter{\iffalse}\fi
}\@secondoftwo

We still have an extra closing brace... But \iffalse}\fi is expanded and disappears, and \@thirdoffour takes the arguments {}\@secondoftwo{true branch}{false branch}, and only leaves {true branch}.

The star is just some random non-brace token, here so that \string does not act on the next (closing brace) token if the argument is empty. Some tests:

% For testing purposes only:
\def\test#1{\message{\iffirst@brace{#1}{true}{false}}}
\test{{ab}cd}  \test{a{bc}d}  \test{ {ab}d}  % "true false false"
\test{{}}      \test{ }       \test{}        % "true false false"

Initially, I had written the code using the LaTeX3 convention (the expl3 package). It defines a \tl_if_first_brace:nTF equivalent to the above, and also the variants \tl_if_first_brace:nT and \tl_if_first_brace:nF, which only have a true branch or false branch. It also defines a predicate \tl_if_first_brace_p:n, which has no equivalent in "plain" LaTeX2e.

\RequirePackage{expl3}
\ExplSyntaxOn
\prg_new_conditional:Npnn \tl_if_first_brace:n #1 {p,T,F,TF} {
  \exp_after:wN \use_none:n \exp_after:wN { \exp_after:wN { 
      \token_to_str:N #1 ?
    }\prg_return_true: \exp_after:wN \use_none:nn \exp_after:wN {\if_false:}\fi:
  }\prg_return_false:
}
1
7

A brace trick I found useful is in this answer of mine for typesetting continued fractions with a simpler syntax than

1+\cfrac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}}

that requires keeping track of the nesting; using

\xcontfrac{1;2,3,4}

seems quite easier. The idea is to loop through the list 2,3,4 and build a token list containing

1+
\noexpand\cfrac{1}\iftrue{\else}\fi 2+
  \noexpand\cfrac{1}\iftrue{\else}\fi 3+
    \noexpand\cfrac{1}\iftrue{\else}\fi 4

and another one containing

    \iffalse{\else}\fi
  \iffalse{\else}\fi
\iffalse{\else}\fi

(indenting is added for clarity) so that pasting these to token list and feeding the result to \edef builds the desired one, so that finally \cfrac can do its job.

1
  • The l3regex implementation uses a similar trick to build the result of a regular expression replacement (with two (three) consecutive \edef expansions). An arbitrary token list, say a{b}# can be split into individual tokens, but to manipulate those we need to make them into balanced token lists: a, {\iffalse}\fi, b, \iffalse{\fi} and ##. Those are stored in \toks registers. The registers are unpacked by a first \edef, giving a{\iffalse}\fi b\iffalse{\fi}##, and a second \edef gives a{b}#. Getting it to work for arbitrary tokens is hard :). Mar 1, 2012 at 23:14

You must log in to answer this question.

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