Understanding Brace Hacks












29















I am trying to better understand brace hacks. The issue was brought to my attention in egreg's answer, Conflict between eqnarray and tabstackengine, that tabstackengine's failure to protect inner alignment groups could be fixed using brace hacks. David Carlisle pointed me to the TeXbook, and I find them described on p.385.



Now the one used by egreg was similar to but different from the ones on p.385. Below I summarize the 4 given by Knuth, and add 2 more based on egreg's answer, with regards to how they affect the master and balance counter, when expanded and prior to expansion:



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1
bgroup 0 0 0 0
iffalse{fi 1 1 0 1
ifnum0=`{fi 0 1 0 1

{iffalse}fi 0 0 1 0
{ifnum0=`}fi 1 0 1 0


I realize that in addition to alignment groups, brace types influence how math binary/unary categories communicate to adjacent atoms, they can limit the scope of defined data, and some can or cannot be used in macro/environment definitions without the corresponding [balanced] brace.



To this end, I set up an MWE to test the 6 brace types shown above, as well as begingroup...endgroup, to see how they behaved and scored each of the results:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect inner alignment group\
0/1 does not/does communicate binary nature across boundary\
0/1 does not/does preserve defined data across boundary\
0/1 does not/does work within begining/end of environment definition

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 1000

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 1110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 0110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 1001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 0101

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}meaning Q
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end{document}


enter image description here



The grade is a 4-digit number, each successive digit describing a "do or not do" to 4 questions:




  1. gets a 1 if the brace method protects inner alignment groups (A/OK vs. BAD ALIGNMENT)


  2. gets a 1 if surrounding math atoms can communicate their presence through the boundary (A = B vs. A=B)


  3. gets a 1 if an inner macro definition is preserved outside of the grouping (macro:-> XYZ vs. undefined)


  4. gets a 1 if the unbalanced version of the brace type can be used in an environment (&&& vs. BAD ENV. DEFINITION).



For completeness, I guess I should note that the absence of any bracing (not performed in my MWE) would get a score of 0111.



This was all very enlightening to me, but I had originally been thinking that there must be more differences (tests to perform) that can differentiate these methods that I am missing. However, that thinking was based on a typo in my code that Marcel caught and pointed out. Nonetheless, there may be more tests to further differentiate the results. Also, my results (the "grade") describes things differently than Knuth, who instead describes the differences in terms of effects on master and balance counters, for both expanded and unexpanded states of input.



I also note that my limited set of tests would indicate that bgroup...egroup behaves in the exact same manner as {iffalse}fi...iffalse{fi}. Is this actually the case?



So the question is simply, are there other tests can be run to further differentiate the behavior of the seven different bracing techniques shown in my MWE? Are there additional brace hacks that bring further nuance to the question?



p.s. I have submitted a revision of tabstackengine to ctan.org today, which fixes the inner alignment group issue and provides some new features.





RESULTS, THANKS TO MARCEL'S ANSWER AND GuM's SUGGESTION



Thanks to Marcel's answer, two important things were learned:




  1. I had a typo in my original question that was causing one of my misunderstandings (without taking anything away from Marcel's answer, I edited the original question to fix it since typos generally make for really bad questions)


  2. A 5th test was added to the mix, to further differentiate the grade: whether the brace hack could be used to delimit an edef.



In addition, GuM suggested two possible brace hacks, one of which proved uniquely successful: iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi. I have added it to my list.



I show those updated results below, and include the control case of "no delimiters whatsoever". With this 5th test, the results are fully clarified, showing that no two brace hacks perform identically for the 5 tests, and it further emerges that some are complementary (opposite) bracing conditions:




  1. The case of no delimiters and brace {...} delimiters were complementary, with grades of 01110 and 10001, respectively.


  2. the case of iffalse{fi...iffalse}fi and {iffalse}fi...iffalse{fi} were complementary, with grades of 11100 and 00011, respectively.


  3. The case of ifnum0=‘{fi...ifnum0=‘}fi and {ifnum0=‘}fi...ifnum0=‘{fi} were complementary, with grades of 01100 and 10011, respectively.


  4. The remaining two cases, bgroup...egroup and begingroup...endgroup were similar, except for the well known distinction that the latter will allow math classes to see across the boundary to adjacent math atoms. Their respective scores were 00010 and 01010.


  5. Gum's suggested brace hack has the most comprehensive score of 11110, which means it protects/isolates inner alignment groups, provides knowledge of math atoms across boundaries, preserves inner defined data across the outer boundary, and works as an open/close pair in begin/end environment definitions. It only fails in that it cannot delimit an edef.



Perhaps Marcel's coolest discernment in his answer was that the {iffalse}fi...iffalse{fi} brace hack could be used across an environment definition in order to capture the fully expanded contents of the environment; A very unique insight.



The updated MWE, incorporating all that I've learned here:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm,top=2cm,bottom=2cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect/isolate inner alignment groups.\
0/1 does not/does provide knowledge of math atoms across boundary.\
0/1 does not/does preserve inner-defined data across outer boundary.\
0/1 does not/does work as open/close pair in the begining/end of environment definition.\
0/1 does not/does work as delimiters to an textbackslash edef.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|...| (absence of delimiters)hfill Grade 01110

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 10001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{today}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 00010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbgrouptodayegroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fitodayiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fitodayifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 00011

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse}fitodayiffalse{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 10011

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`}fitodayifnum0=`{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 01010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbegingrouptodayendgroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fiifnum0=`}fi...ifnum0=`{fiiffalse}fi|hfill
Grade 11110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiifnum0=`}fiblech{A&OK}ifnum0=`{fiiffalse}fi
end{aligned}$hfill
$Aiffalse{fiifnum0=`}fi=ifnum0=`{fiiffalse}fi B$
hfill$iffalse{fiifnum0=`}fidefQ{XYZ}ifnum0=`{fiiffalse}fimeaningQ$

renewenvironment{QQQ}{iffalse{fiifnum0=`}ficatcode`&=12 }{ifnum0=`{fiiffalse}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fiifnum0=`}fitodayifnum0=`{fiiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clearpage

{LARGEbfseries FAILED CASES}

The following case has a score of verb|01110|, which is identical
to the case of ``absent delimiters.''
Thus, it is currently excluded as a ``brace hack'' as it provides no added value.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fiiffalse}fi...iffalse{fiifnum0=`}fi|hfill
Grade 01110

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiiffalse}fiblech{A&OK}iffalse{fiifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fiiffalse}fi=iffalse{fiifnum0=`}fi B$
hfill$ifnum0=`{fiiffalse}fidefQ{XYZ}iffalse{fiifnum0=`}fimeaningQ$

renewenvironment{QQQ}{ifnum0=`{fiiffalse}ficatcode`&=12 }{iffalse{fiifnum0=`}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fiiffalse}fitodayiffalse{fiifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

These two cases below produce the same grades as the same as the simpler
verb|iffalse| and verb|ifnum| cases.
Thus, they provide no added value to the list of ``brace hacks.''

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse{fi}...{iffalse}fi}|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {iffalse{fi}blech{A&OK}{iffalse}fi}
end{aligned}$hfill
$A{iffalse{fi}={iffalse}fi}B$%
hfill${iffalse{fi}defQ{XYZ}{iffalse}fi}meaningQ$

%renewenvironment{QQQ}{{iffalse{fi}catcode`&=12 }{{iffalse}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse{fi}executed, not verb|edef|ed{iffalse}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`{fi}...{ifnum0=`}fi}|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ BAD ALIGNMENT%{ifnum0=`{fi}blech{A&OK}{ifnum0=`}fi}
end{aligned}$hfill
$A{ifnum0=`{fi}={ifnum0=`}fi}B$%
hfill${ifnum0=`{fi}defQ{XYZ}{ifnum0=`}fi}meaningQ$

%renewenvironment{QQQ}{{ifnum0=`{fi}catcode`&=12 }{{ifnum0=`}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`{fi}executed, not verb|edef|ed{ifnum0=`}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end{document}


enter image description here



enter image description here



The updated counter-change table is



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1 (Knuth)
bgroup 0 0 0 0 (Knuth)
iffalse{fi 1 1 0 1 (Knuth)
ifnum0=`{fi 0 1 0 1 (Knuth)

{iffalse}fi 0 0 1 0 (egreg inspired)
{ifnum0=`}fi 1 0 1 0 (egreg used)
iffalse{fiifnum0=`}fi 1 0 0 0 (GuM suggestion)


Some correlations between my 5-digit grades and this counter table can be established:




  1. In order to get a grade of 1 in the 1st digit (the ability to protect/isolate inner alignment groups), the expanded master counter must increase by 1.


  2. In order to get a grade of 1 in the 4th digit (be able to use as open/close pair in the begin/end of an environment), the unexpanded balance (or master) counter must not increase (has a value of 0).


  3. In order to provide delimiters for an edef, the expanded balance counter must increase by 1.



Unrelated to the counter table, but observed from the graded results (excluding begingroup...endgroup which is in a category by itself), grades of 1 in digits 2 and 3 (knowledge of math atoms across boundary and preservation of inner-defined data) can only occur if there are no unconditional occurrences of {...} or bgroup...egroup.



Thanks for putting up with this extended question!










share|improve this question




















  • 5





    Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

    – ShreevatsaR
    Mar 6 '18 at 4:30






  • 2





    I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

    – GuM
    Mar 6 '18 at 8:42











  • @GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

    – Steven B. Segletes
    Mar 6 '18 at 15:24













  • @StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

    – Marcel Krüger
    Mar 6 '18 at 16:00






  • 1





    @GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

    – Steven B. Segletes
    Mar 6 '18 at 16:29


















29















I am trying to better understand brace hacks. The issue was brought to my attention in egreg's answer, Conflict between eqnarray and tabstackengine, that tabstackengine's failure to protect inner alignment groups could be fixed using brace hacks. David Carlisle pointed me to the TeXbook, and I find them described on p.385.



Now the one used by egreg was similar to but different from the ones on p.385. Below I summarize the 4 given by Knuth, and add 2 more based on egreg's answer, with regards to how they affect the master and balance counter, when expanded and prior to expansion:



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1
bgroup 0 0 0 0
iffalse{fi 1 1 0 1
ifnum0=`{fi 0 1 0 1

{iffalse}fi 0 0 1 0
{ifnum0=`}fi 1 0 1 0


I realize that in addition to alignment groups, brace types influence how math binary/unary categories communicate to adjacent atoms, they can limit the scope of defined data, and some can or cannot be used in macro/environment definitions without the corresponding [balanced] brace.



To this end, I set up an MWE to test the 6 brace types shown above, as well as begingroup...endgroup, to see how they behaved and scored each of the results:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect inner alignment group\
0/1 does not/does communicate binary nature across boundary\
0/1 does not/does preserve defined data across boundary\
0/1 does not/does work within begining/end of environment definition

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 1000

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 1110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 0110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 1001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 0101

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}meaning Q
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end{document}


enter image description here



The grade is a 4-digit number, each successive digit describing a "do or not do" to 4 questions:




  1. gets a 1 if the brace method protects inner alignment groups (A/OK vs. BAD ALIGNMENT)


  2. gets a 1 if surrounding math atoms can communicate their presence through the boundary (A = B vs. A=B)


  3. gets a 1 if an inner macro definition is preserved outside of the grouping (macro:-> XYZ vs. undefined)


  4. gets a 1 if the unbalanced version of the brace type can be used in an environment (&&& vs. BAD ENV. DEFINITION).



For completeness, I guess I should note that the absence of any bracing (not performed in my MWE) would get a score of 0111.



This was all very enlightening to me, but I had originally been thinking that there must be more differences (tests to perform) that can differentiate these methods that I am missing. However, that thinking was based on a typo in my code that Marcel caught and pointed out. Nonetheless, there may be more tests to further differentiate the results. Also, my results (the "grade") describes things differently than Knuth, who instead describes the differences in terms of effects on master and balance counters, for both expanded and unexpanded states of input.



I also note that my limited set of tests would indicate that bgroup...egroup behaves in the exact same manner as {iffalse}fi...iffalse{fi}. Is this actually the case?



So the question is simply, are there other tests can be run to further differentiate the behavior of the seven different bracing techniques shown in my MWE? Are there additional brace hacks that bring further nuance to the question?



p.s. I have submitted a revision of tabstackengine to ctan.org today, which fixes the inner alignment group issue and provides some new features.





RESULTS, THANKS TO MARCEL'S ANSWER AND GuM's SUGGESTION



Thanks to Marcel's answer, two important things were learned:




  1. I had a typo in my original question that was causing one of my misunderstandings (without taking anything away from Marcel's answer, I edited the original question to fix it since typos generally make for really bad questions)


  2. A 5th test was added to the mix, to further differentiate the grade: whether the brace hack could be used to delimit an edef.



In addition, GuM suggested two possible brace hacks, one of which proved uniquely successful: iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi. I have added it to my list.



I show those updated results below, and include the control case of "no delimiters whatsoever". With this 5th test, the results are fully clarified, showing that no two brace hacks perform identically for the 5 tests, and it further emerges that some are complementary (opposite) bracing conditions:




  1. The case of no delimiters and brace {...} delimiters were complementary, with grades of 01110 and 10001, respectively.


  2. the case of iffalse{fi...iffalse}fi and {iffalse}fi...iffalse{fi} were complementary, with grades of 11100 and 00011, respectively.


  3. The case of ifnum0=‘{fi...ifnum0=‘}fi and {ifnum0=‘}fi...ifnum0=‘{fi} were complementary, with grades of 01100 and 10011, respectively.


  4. The remaining two cases, bgroup...egroup and begingroup...endgroup were similar, except for the well known distinction that the latter will allow math classes to see across the boundary to adjacent math atoms. Their respective scores were 00010 and 01010.


  5. Gum's suggested brace hack has the most comprehensive score of 11110, which means it protects/isolates inner alignment groups, provides knowledge of math atoms across boundaries, preserves inner defined data across the outer boundary, and works as an open/close pair in begin/end environment definitions. It only fails in that it cannot delimit an edef.



Perhaps Marcel's coolest discernment in his answer was that the {iffalse}fi...iffalse{fi} brace hack could be used across an environment definition in order to capture the fully expanded contents of the environment; A very unique insight.



The updated MWE, incorporating all that I've learned here:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm,top=2cm,bottom=2cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect/isolate inner alignment groups.\
0/1 does not/does provide knowledge of math atoms across boundary.\
0/1 does not/does preserve inner-defined data across outer boundary.\
0/1 does not/does work as open/close pair in the begining/end of environment definition.\
0/1 does not/does work as delimiters to an textbackslash edef.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|...| (absence of delimiters)hfill Grade 01110

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 10001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{today}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 00010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbgrouptodayegroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fitodayiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fitodayifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 00011

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse}fitodayiffalse{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 10011

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`}fitodayifnum0=`{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 01010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbegingrouptodayendgroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fiifnum0=`}fi...ifnum0=`{fiiffalse}fi|hfill
Grade 11110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiifnum0=`}fiblech{A&OK}ifnum0=`{fiiffalse}fi
end{aligned}$hfill
$Aiffalse{fiifnum0=`}fi=ifnum0=`{fiiffalse}fi B$
hfill$iffalse{fiifnum0=`}fidefQ{XYZ}ifnum0=`{fiiffalse}fimeaningQ$

renewenvironment{QQQ}{iffalse{fiifnum0=`}ficatcode`&=12 }{ifnum0=`{fiiffalse}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fiifnum0=`}fitodayifnum0=`{fiiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clearpage

{LARGEbfseries FAILED CASES}

The following case has a score of verb|01110|, which is identical
to the case of ``absent delimiters.''
Thus, it is currently excluded as a ``brace hack'' as it provides no added value.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fiiffalse}fi...iffalse{fiifnum0=`}fi|hfill
Grade 01110

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiiffalse}fiblech{A&OK}iffalse{fiifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fiiffalse}fi=iffalse{fiifnum0=`}fi B$
hfill$ifnum0=`{fiiffalse}fidefQ{XYZ}iffalse{fiifnum0=`}fimeaningQ$

renewenvironment{QQQ}{ifnum0=`{fiiffalse}ficatcode`&=12 }{iffalse{fiifnum0=`}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fiiffalse}fitodayiffalse{fiifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

These two cases below produce the same grades as the same as the simpler
verb|iffalse| and verb|ifnum| cases.
Thus, they provide no added value to the list of ``brace hacks.''

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse{fi}...{iffalse}fi}|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {iffalse{fi}blech{A&OK}{iffalse}fi}
end{aligned}$hfill
$A{iffalse{fi}={iffalse}fi}B$%
hfill${iffalse{fi}defQ{XYZ}{iffalse}fi}meaningQ$

%renewenvironment{QQQ}{{iffalse{fi}catcode`&=12 }{{iffalse}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse{fi}executed, not verb|edef|ed{iffalse}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`{fi}...{ifnum0=`}fi}|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ BAD ALIGNMENT%{ifnum0=`{fi}blech{A&OK}{ifnum0=`}fi}
end{aligned}$hfill
$A{ifnum0=`{fi}={ifnum0=`}fi}B$%
hfill${ifnum0=`{fi}defQ{XYZ}{ifnum0=`}fi}meaningQ$

%renewenvironment{QQQ}{{ifnum0=`{fi}catcode`&=12 }{{ifnum0=`}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`{fi}executed, not verb|edef|ed{ifnum0=`}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end{document}


enter image description here



enter image description here



The updated counter-change table is



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1 (Knuth)
bgroup 0 0 0 0 (Knuth)
iffalse{fi 1 1 0 1 (Knuth)
ifnum0=`{fi 0 1 0 1 (Knuth)

{iffalse}fi 0 0 1 0 (egreg inspired)
{ifnum0=`}fi 1 0 1 0 (egreg used)
iffalse{fiifnum0=`}fi 1 0 0 0 (GuM suggestion)


Some correlations between my 5-digit grades and this counter table can be established:




  1. In order to get a grade of 1 in the 1st digit (the ability to protect/isolate inner alignment groups), the expanded master counter must increase by 1.


  2. In order to get a grade of 1 in the 4th digit (be able to use as open/close pair in the begin/end of an environment), the unexpanded balance (or master) counter must not increase (has a value of 0).


  3. In order to provide delimiters for an edef, the expanded balance counter must increase by 1.



Unrelated to the counter table, but observed from the graded results (excluding begingroup...endgroup which is in a category by itself), grades of 1 in digits 2 and 3 (knowledge of math atoms across boundary and preservation of inner-defined data) can only occur if there are no unconditional occurrences of {...} or bgroup...egroup.



Thanks for putting up with this extended question!










share|improve this question




















  • 5





    Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

    – ShreevatsaR
    Mar 6 '18 at 4:30






  • 2





    I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

    – GuM
    Mar 6 '18 at 8:42











  • @GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

    – Steven B. Segletes
    Mar 6 '18 at 15:24













  • @StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

    – Marcel Krüger
    Mar 6 '18 at 16:00






  • 1





    @GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

    – Steven B. Segletes
    Mar 6 '18 at 16:29
















29












29








29


4






I am trying to better understand brace hacks. The issue was brought to my attention in egreg's answer, Conflict between eqnarray and tabstackengine, that tabstackengine's failure to protect inner alignment groups could be fixed using brace hacks. David Carlisle pointed me to the TeXbook, and I find them described on p.385.



Now the one used by egreg was similar to but different from the ones on p.385. Below I summarize the 4 given by Knuth, and add 2 more based on egreg's answer, with regards to how they affect the master and balance counter, when expanded and prior to expansion:



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1
bgroup 0 0 0 0
iffalse{fi 1 1 0 1
ifnum0=`{fi 0 1 0 1

{iffalse}fi 0 0 1 0
{ifnum0=`}fi 1 0 1 0


I realize that in addition to alignment groups, brace types influence how math binary/unary categories communicate to adjacent atoms, they can limit the scope of defined data, and some can or cannot be used in macro/environment definitions without the corresponding [balanced] brace.



To this end, I set up an MWE to test the 6 brace types shown above, as well as begingroup...endgroup, to see how they behaved and scored each of the results:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect inner alignment group\
0/1 does not/does communicate binary nature across boundary\
0/1 does not/does preserve defined data across boundary\
0/1 does not/does work within begining/end of environment definition

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 1000

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 1110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 0110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 1001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 0101

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}meaning Q
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end{document}


enter image description here



The grade is a 4-digit number, each successive digit describing a "do or not do" to 4 questions:




  1. gets a 1 if the brace method protects inner alignment groups (A/OK vs. BAD ALIGNMENT)


  2. gets a 1 if surrounding math atoms can communicate their presence through the boundary (A = B vs. A=B)


  3. gets a 1 if an inner macro definition is preserved outside of the grouping (macro:-> XYZ vs. undefined)


  4. gets a 1 if the unbalanced version of the brace type can be used in an environment (&&& vs. BAD ENV. DEFINITION).



For completeness, I guess I should note that the absence of any bracing (not performed in my MWE) would get a score of 0111.



This was all very enlightening to me, but I had originally been thinking that there must be more differences (tests to perform) that can differentiate these methods that I am missing. However, that thinking was based on a typo in my code that Marcel caught and pointed out. Nonetheless, there may be more tests to further differentiate the results. Also, my results (the "grade") describes things differently than Knuth, who instead describes the differences in terms of effects on master and balance counters, for both expanded and unexpanded states of input.



I also note that my limited set of tests would indicate that bgroup...egroup behaves in the exact same manner as {iffalse}fi...iffalse{fi}. Is this actually the case?



So the question is simply, are there other tests can be run to further differentiate the behavior of the seven different bracing techniques shown in my MWE? Are there additional brace hacks that bring further nuance to the question?



p.s. I have submitted a revision of tabstackengine to ctan.org today, which fixes the inner alignment group issue and provides some new features.





RESULTS, THANKS TO MARCEL'S ANSWER AND GuM's SUGGESTION



Thanks to Marcel's answer, two important things were learned:




  1. I had a typo in my original question that was causing one of my misunderstandings (without taking anything away from Marcel's answer, I edited the original question to fix it since typos generally make for really bad questions)


  2. A 5th test was added to the mix, to further differentiate the grade: whether the brace hack could be used to delimit an edef.



In addition, GuM suggested two possible brace hacks, one of which proved uniquely successful: iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi. I have added it to my list.



I show those updated results below, and include the control case of "no delimiters whatsoever". With this 5th test, the results are fully clarified, showing that no two brace hacks perform identically for the 5 tests, and it further emerges that some are complementary (opposite) bracing conditions:




  1. The case of no delimiters and brace {...} delimiters were complementary, with grades of 01110 and 10001, respectively.


  2. the case of iffalse{fi...iffalse}fi and {iffalse}fi...iffalse{fi} were complementary, with grades of 11100 and 00011, respectively.


  3. The case of ifnum0=‘{fi...ifnum0=‘}fi and {ifnum0=‘}fi...ifnum0=‘{fi} were complementary, with grades of 01100 and 10011, respectively.


  4. The remaining two cases, bgroup...egroup and begingroup...endgroup were similar, except for the well known distinction that the latter will allow math classes to see across the boundary to adjacent math atoms. Their respective scores were 00010 and 01010.


  5. Gum's suggested brace hack has the most comprehensive score of 11110, which means it protects/isolates inner alignment groups, provides knowledge of math atoms across boundaries, preserves inner defined data across the outer boundary, and works as an open/close pair in begin/end environment definitions. It only fails in that it cannot delimit an edef.



Perhaps Marcel's coolest discernment in his answer was that the {iffalse}fi...iffalse{fi} brace hack could be used across an environment definition in order to capture the fully expanded contents of the environment; A very unique insight.



The updated MWE, incorporating all that I've learned here:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm,top=2cm,bottom=2cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect/isolate inner alignment groups.\
0/1 does not/does provide knowledge of math atoms across boundary.\
0/1 does not/does preserve inner-defined data across outer boundary.\
0/1 does not/does work as open/close pair in the begining/end of environment definition.\
0/1 does not/does work as delimiters to an textbackslash edef.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|...| (absence of delimiters)hfill Grade 01110

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 10001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{today}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 00010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbgrouptodayegroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fitodayiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fitodayifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 00011

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse}fitodayiffalse{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 10011

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`}fitodayifnum0=`{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 01010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbegingrouptodayendgroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fiifnum0=`}fi...ifnum0=`{fiiffalse}fi|hfill
Grade 11110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiifnum0=`}fiblech{A&OK}ifnum0=`{fiiffalse}fi
end{aligned}$hfill
$Aiffalse{fiifnum0=`}fi=ifnum0=`{fiiffalse}fi B$
hfill$iffalse{fiifnum0=`}fidefQ{XYZ}ifnum0=`{fiiffalse}fimeaningQ$

renewenvironment{QQQ}{iffalse{fiifnum0=`}ficatcode`&=12 }{ifnum0=`{fiiffalse}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fiifnum0=`}fitodayifnum0=`{fiiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clearpage

{LARGEbfseries FAILED CASES}

The following case has a score of verb|01110|, which is identical
to the case of ``absent delimiters.''
Thus, it is currently excluded as a ``brace hack'' as it provides no added value.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fiiffalse}fi...iffalse{fiifnum0=`}fi|hfill
Grade 01110

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiiffalse}fiblech{A&OK}iffalse{fiifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fiiffalse}fi=iffalse{fiifnum0=`}fi B$
hfill$ifnum0=`{fiiffalse}fidefQ{XYZ}iffalse{fiifnum0=`}fimeaningQ$

renewenvironment{QQQ}{ifnum0=`{fiiffalse}ficatcode`&=12 }{iffalse{fiifnum0=`}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fiiffalse}fitodayiffalse{fiifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

These two cases below produce the same grades as the same as the simpler
verb|iffalse| and verb|ifnum| cases.
Thus, they provide no added value to the list of ``brace hacks.''

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse{fi}...{iffalse}fi}|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {iffalse{fi}blech{A&OK}{iffalse}fi}
end{aligned}$hfill
$A{iffalse{fi}={iffalse}fi}B$%
hfill${iffalse{fi}defQ{XYZ}{iffalse}fi}meaningQ$

%renewenvironment{QQQ}{{iffalse{fi}catcode`&=12 }{{iffalse}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse{fi}executed, not verb|edef|ed{iffalse}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`{fi}...{ifnum0=`}fi}|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ BAD ALIGNMENT%{ifnum0=`{fi}blech{A&OK}{ifnum0=`}fi}
end{aligned}$hfill
$A{ifnum0=`{fi}={ifnum0=`}fi}B$%
hfill${ifnum0=`{fi}defQ{XYZ}{ifnum0=`}fi}meaningQ$

%renewenvironment{QQQ}{{ifnum0=`{fi}catcode`&=12 }{{ifnum0=`}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`{fi}executed, not verb|edef|ed{ifnum0=`}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end{document}


enter image description here



enter image description here



The updated counter-change table is



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1 (Knuth)
bgroup 0 0 0 0 (Knuth)
iffalse{fi 1 1 0 1 (Knuth)
ifnum0=`{fi 0 1 0 1 (Knuth)

{iffalse}fi 0 0 1 0 (egreg inspired)
{ifnum0=`}fi 1 0 1 0 (egreg used)
iffalse{fiifnum0=`}fi 1 0 0 0 (GuM suggestion)


Some correlations between my 5-digit grades and this counter table can be established:




  1. In order to get a grade of 1 in the 1st digit (the ability to protect/isolate inner alignment groups), the expanded master counter must increase by 1.


  2. In order to get a grade of 1 in the 4th digit (be able to use as open/close pair in the begin/end of an environment), the unexpanded balance (or master) counter must not increase (has a value of 0).


  3. In order to provide delimiters for an edef, the expanded balance counter must increase by 1.



Unrelated to the counter table, but observed from the graded results (excluding begingroup...endgroup which is in a category by itself), grades of 1 in digits 2 and 3 (knowledge of math atoms across boundary and preservation of inner-defined data) can only occur if there are no unconditional occurrences of {...} or bgroup...egroup.



Thanks for putting up with this extended question!










share|improve this question
















I am trying to better understand brace hacks. The issue was brought to my attention in egreg's answer, Conflict between eqnarray and tabstackengine, that tabstackengine's failure to protect inner alignment groups could be fixed using brace hacks. David Carlisle pointed me to the TeXbook, and I find them described on p.385.



Now the one used by egreg was similar to but different from the ones on p.385. Below I summarize the 4 given by Knuth, and add 2 more based on egreg's answer, with regards to how they affect the master and balance counter, when expanded and prior to expansion:



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1
bgroup 0 0 0 0
iffalse{fi 1 1 0 1
ifnum0=`{fi 0 1 0 1

{iffalse}fi 0 0 1 0
{ifnum0=`}fi 1 0 1 0


I realize that in addition to alignment groups, brace types influence how math binary/unary categories communicate to adjacent atoms, they can limit the scope of defined data, and some can or cannot be used in macro/environment definitions without the corresponding [balanced] brace.



To this end, I set up an MWE to test the 6 brace types shown above, as well as begingroup...endgroup, to see how they behaved and scored each of the results:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect inner alignment group\
0/1 does not/does communicate binary nature across boundary\
0/1 does not/does preserve defined data across boundary\
0/1 does not/does work within begining/end of environment definition

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 1000

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 1110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 0110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 0001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 1001

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 0101

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}meaning Q
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

end{document}


enter image description here



The grade is a 4-digit number, each successive digit describing a "do or not do" to 4 questions:




  1. gets a 1 if the brace method protects inner alignment groups (A/OK vs. BAD ALIGNMENT)


  2. gets a 1 if surrounding math atoms can communicate their presence through the boundary (A = B vs. A=B)


  3. gets a 1 if an inner macro definition is preserved outside of the grouping (macro:-> XYZ vs. undefined)


  4. gets a 1 if the unbalanced version of the brace type can be used in an environment (&&& vs. BAD ENV. DEFINITION).



For completeness, I guess I should note that the absence of any bracing (not performed in my MWE) would get a score of 0111.



This was all very enlightening to me, but I had originally been thinking that there must be more differences (tests to perform) that can differentiate these methods that I am missing. However, that thinking was based on a typo in my code that Marcel caught and pointed out. Nonetheless, there may be more tests to further differentiate the results. Also, my results (the "grade") describes things differently than Knuth, who instead describes the differences in terms of effects on master and balance counters, for both expanded and unexpanded states of input.



I also note that my limited set of tests would indicate that bgroup...egroup behaves in the exact same manner as {iffalse}fi...iffalse{fi}. Is this actually the case?



So the question is simply, are there other tests can be run to further differentiate the behavior of the seven different bracing techniques shown in my MWE? Are there additional brace hacks that bring further nuance to the question?



p.s. I have submitted a revision of tabstackengine to ctan.org today, which fixes the inner alignment group issue and provides some new features.





RESULTS, THANKS TO MARCEL'S ANSWER AND GuM's SUGGESTION



Thanks to Marcel's answer, two important things were learned:




  1. I had a typo in my original question that was causing one of my misunderstandings (without taking anything away from Marcel's answer, I edited the original question to fix it since typos generally make for really bad questions)


  2. A 5th test was added to the mix, to further differentiate the grade: whether the brace hack could be used to delimit an edef.



In addition, GuM suggested two possible brace hacks, one of which proved uniquely successful: iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi. I have added it to my list.



I show those updated results below, and include the control case of "no delimiters whatsoever". With this 5th test, the results are fully clarified, showing that no two brace hacks perform identically for the 5 tests, and it further emerges that some are complementary (opposite) bracing conditions:




  1. The case of no delimiters and brace {...} delimiters were complementary, with grades of 01110 and 10001, respectively.


  2. the case of iffalse{fi...iffalse}fi and {iffalse}fi...iffalse{fi} were complementary, with grades of 11100 and 00011, respectively.


  3. The case of ifnum0=‘{fi...ifnum0=‘}fi and {ifnum0=‘}fi...ifnum0=‘{fi} were complementary, with grades of 01100 and 10011, respectively.


  4. The remaining two cases, bgroup...egroup and begingroup...endgroup were similar, except for the well known distinction that the latter will allow math classes to see across the boundary to adjacent math atoms. Their respective scores were 00010 and 01010.


  5. Gum's suggested brace hack has the most comprehensive score of 11110, which means it protects/isolates inner alignment groups, provides knowledge of math atoms across boundaries, preserves inner defined data across the outer boundary, and works as an open/close pair in begin/end environment definitions. It only fails in that it cannot delimit an edef.



Perhaps Marcel's coolest discernment in his answer was that the {iffalse}fi...iffalse{fi} brace hack could be used across an environment definition in order to capture the fully expanded contents of the environment; A very unique insight.



The updated MWE, incorporating all that I've learned here:



% BRACE HACK TESTING/LEARNING
%
documentclass{article}
usepackage{amsmath}
usepackage[margin=3cm,top=2cm,bottom=2cm]{geometry}
newenvironment{QQQ}{}{}
defblech#1{blechaux#1relax}
defblechaux#1&#2relax{#1/#2}
begin{document}
GRADING ELEMENTS:\
0/1 does not/does protect/isolate inner alignment groups.\
0/1 does not/does provide knowledge of math atoms across boundary.\
0/1 does not/does preserve inner-defined data across outer boundary.\
0/1 does not/does work as open/close pair in the begining/end of environment definition.\
0/1 does not/does work as delimiters to an textbackslash edef.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|...| (absence of delimiters)hfill Grade 01110

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{...}|hfill Grade 10001

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {blech{A&OK}}
end{aligned}$hfill
$A{=}B$hfill${defQ{XYZ}}meaningQ$

%renewenvironment{QQQ}{{catcode`&=12 }{}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{today}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|bgroup...egroup|hfill Grade 00010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%bgroupblech{A&OK}egroup
end{aligned}$hfill
$Abgroup=egroup B$hfill$bgroupdefQ{XYZ}egroupmeaningQ$

renewenvironment{QQQ}{bgroupcatcode`&=12 }{egroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbgrouptodayegroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fi...iffalse}fi|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiblech{A&OK}iffalse}fi
end{aligned}$hfill
$Aiffalse{fi=iffalse}fi B$hfill$iffalse{fidefQ{XYZ}iffalse}fimeaningQ$

%renewenvironment{QQQ}{iffalse{ficatcode`&=12 }{iffalse}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fitodayiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fi...ifnum0=`}fi|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiblech{A&OK}ifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fi=ifnum0=`}fi B$hfill$ifnum0=`{fidefQ{XYZ}ifnum0=`}fimeaningQ$

%renewenvironment{QQQ}{ifnum0=`{ficatcode`&=12 }{ifnum0=`}fi}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fitodayifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse}fi...iffalse{fi}|hfill Grade 00011

$begin{aligned}
y&=mx + b\
E&=mc^2
+ textrm{BAD ALIGNMENT}% {iffalse}fiblech{A&OK}iffalse{fi}
end{aligned}$hfill
$A{iffalse}fi=iffalse{fi} B$hfill${iffalse}fidefQ{XYZ}iffalse{fi}meaningQ$

renewenvironment{QQQ}{{iffalse}ficatcode`&=12 }{iffalse{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse}fitodayiffalse{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`}fi...ifnum0=`{fi}|hfill Grade 10011

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}
end{aligned}$hfill
$A{ifnum0=`}fi=ifnum0=`{fi}B$hfill${ifnum0=`}fidefQ{XYZ}ifnum0=`{fi}meaningQ$

renewenvironment{QQQ}{{ifnum0=`}ficatcode`&=12 }{ifnum0=`{fi}}
begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`}fitodayifnum0=`{fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|begingroup...endgroup|hfill Grade 01010

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%begingroupblech{A&OK}endgroup}
end{aligned}$hfill
$Abegingroup=endgroup B$hfill$begingroupdefQ{XYZ}endgroupmeaningQ$

renewenvironment{QQQ}{begingroupcatcode`&=12 }{endgroup}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQbegingrouptodayendgroup[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|iffalse{fiifnum0=`}fi...ifnum0=`{fiiffalse}fi|hfill
Grade 11110

$begin{aligned}
y&=mx + b\
E&=mc^2
+ iffalse{fiifnum0=`}fiblech{A&OK}ifnum0=`{fiiffalse}fi
end{aligned}$hfill
$Aiffalse{fiifnum0=`}fi=ifnum0=`{fiiffalse}fi B$
hfill$iffalse{fiifnum0=`}fidefQ{XYZ}ifnum0=`{fiiffalse}fimeaningQ$

renewenvironment{QQQ}{iffalse{fiifnum0=`}ficatcode`&=12 }{ifnum0=`{fiiffalse}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQiffalse{fiifnum0=`}fitodayifnum0=`{fiiffalse}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clearpage

{LARGEbfseries FAILED CASES}

The following case has a score of verb|01110|, which is identical
to the case of ``absent delimiters.''
Thus, it is currently excluded as a ``brace hack'' as it provides no added value.

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|ifnum0=`{fiiffalse}fi...iffalse{fiifnum0=`}fi|hfill
Grade 01110

$begin{aligned}
y&=mx + b\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ textrm{BAD ALIGNMENT}%ifnum0=`{fiiffalse}fiblech{A&OK}iffalse{fiifnum0=`}fi
end{aligned}$hfill
$Aifnum0=`{fiiffalse}fi=iffalse{fiifnum0=`}fi B$
hfill$ifnum0=`{fiiffalse}fidefQ{XYZ}iffalse{fiifnum0=`}fimeaningQ$

renewenvironment{QQQ}{ifnum0=`{fiiffalse}ficatcode`&=12 }{iffalse{fiifnum0=`}fi}
begin{QQQ}&&&end{QQQ}
hfill CAN'T EDEF%edefQQifnum0=`{fiiffalse}fitodayiffalse{fiifnum0=`}fi[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

These two cases below produce the same grades as the same as the simpler
verb|iffalse| and verb|ifnum| cases.
Thus, they provide no added value to the list of ``brace hacks.''

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{iffalse{fi}...{iffalse}fi}|hfill Grade 11100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ {iffalse{fi}blech{A&OK}{iffalse}fi}
end{aligned}$hfill
$A{iffalse{fi}={iffalse}fi}B$%
hfill${iffalse{fi}defQ{XYZ}{iffalse}fi}meaningQ$

%renewenvironment{QQQ}{{iffalse{fi}catcode`&=12 }{{iffalse}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{iffalse{fi}executed, not verb|edef|ed{iffalse}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%

$bullet$Case verb|{ifnum0=`{fi}...{ifnum0=`}fi}|hfill Grade 01100

$begin{aligned}
y&=mx + b\
E&=mc^2
+ BAD ALIGNMENT%{ifnum0=`{fi}blech{A&OK}{ifnum0=`}fi}
end{aligned}$hfill
$A{ifnum0=`{fi}={ifnum0=`}fi}B$%
hfill${ifnum0=`{fi}defQ{XYZ}{ifnum0=`}fi}meaningQ$

%renewenvironment{QQQ}{{ifnum0=`{fi}catcode`&=12 }{{ifnum0=`}fi}}
BAD ENV. DEFINITION%begin{QQQ}&&&end{QQQ}
hfilledefQQ{ifnum0=`{fi}executed, not verb|edef|ed{ifnum0=`}fi}[QQ]

noindenthrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end{document}


enter image description here



enter image description here



The updated counter-change table is



TeX Brace Hacks (p.385, TeXbook)
master balance
ex nox ex nox
{ 1 1 1 1 (Knuth)
bgroup 0 0 0 0 (Knuth)
iffalse{fi 1 1 0 1 (Knuth)
ifnum0=`{fi 0 1 0 1 (Knuth)

{iffalse}fi 0 0 1 0 (egreg inspired)
{ifnum0=`}fi 1 0 1 0 (egreg used)
iffalse{fiifnum0=`}fi 1 0 0 0 (GuM suggestion)


Some correlations between my 5-digit grades and this counter table can be established:




  1. In order to get a grade of 1 in the 1st digit (the ability to protect/isolate inner alignment groups), the expanded master counter must increase by 1.


  2. In order to get a grade of 1 in the 4th digit (be able to use as open/close pair in the begin/end of an environment), the unexpanded balance (or master) counter must not increase (has a value of 0).


  3. In order to provide delimiters for an edef, the expanded balance counter must increase by 1.



Unrelated to the counter table, but observed from the graded results (excluding begingroup...endgroup which is in a category by itself), grades of 1 in digits 2 and 3 (knowledge of math atoms across boundary and preservation of inner-defined data) can only occur if there are no unconditional occurrences of {...} or bgroup...egroup.



Thanks for putting up with this extended question!







tex-core braces






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 6 '18 at 17:54







Steven B. Segletes

















asked Mar 5 '18 at 20:23









Steven B. SegletesSteven B. Segletes

155k9200409




155k9200409








  • 5





    Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

    – ShreevatsaR
    Mar 6 '18 at 4:30






  • 2





    I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

    – GuM
    Mar 6 '18 at 8:42











  • @GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

    – Steven B. Segletes
    Mar 6 '18 at 15:24













  • @StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

    – Marcel Krüger
    Mar 6 '18 at 16:00






  • 1





    @GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

    – Steven B. Segletes
    Mar 6 '18 at 16:29
















  • 5





    Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

    – ShreevatsaR
    Mar 6 '18 at 4:30






  • 2





    I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

    – GuM
    Mar 6 '18 at 8:42











  • @GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

    – Steven B. Segletes
    Mar 6 '18 at 15:24













  • @StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

    – Marcel Krüger
    Mar 6 '18 at 16:00






  • 1





    @GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

    – Steven B. Segletes
    Mar 6 '18 at 16:29










5




5





Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

– ShreevatsaR
Mar 6 '18 at 4:30





Thanks for this question; this will be a prime exhibit in showing why TeX macros are such a perverse “language” to write code in. :-)

– ShreevatsaR
Mar 6 '18 at 4:30




2




2





I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

– GuM
Mar 6 '18 at 8:42





I don’t understand exactly where you want to get with this, but perhaps you should also take an interest in iffalse{fiifnum`}=z@fi and ifnum`{=z@fiiffalse}fi.

– GuM
Mar 6 '18 at 8:42













@GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

– Steven B. Segletes
Mar 6 '18 at 15:24







@GuM I also investigated {iffalse{fi}...{iffalse}fi} and {ifnum0=‘{fi}...{ifnum0=‘}fi}. These cases turned out identical to the simpler iffalse{fi...iffalse}fi and ifnum0=‘{fi...ifnum0=‘}fi cases, respectively.

– Steven B. Segletes
Mar 6 '18 at 15:24















@StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

– Marcel Krüger
Mar 6 '18 at 16:00





@StevenB.Segletes You might want to retest the pair suggested by GuM. It normally should score 11110.

– Marcel Krüger
Mar 6 '18 at 16:00




1




1





@GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

– Steven B. Segletes
Mar 6 '18 at 16:29







@GuM As Marcel notes, the case of iffalse{fiifnum0=‘}fi...ifnum0=‘{fiiffalse}fi actually produces a score of 11110 (awesome!!), whereas the case of ifnum0=‘{fiiffalse}fi...iffalse{fiifnum0=‘}fi seems get a score of 01110, which is the same as the "absent delimiters" case.

– Steven B. Segletes
Mar 6 '18 at 16:29












2 Answers
2






active

oldest

votes


















19














The fourth case is actually 0110, the 1110 came from a typo in the code:
Your test



E&=mc^2
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}


is the test for the sixth case, it should be



E&=mc^2
+ ifnum0=`{fiblech{A&OK}ifnum0=`}fi


instead.



This leaves {iffalse}fi...iffalse{fi} and bgroup...egroup.
According to the TeXbook, the difference lies in the expanded version of the balance counter.
The balance counter is used for example for macro definitions and we need expansion, so we can construct an additional test:




  1. Can be used to delimit the definition of an edef.


This will fail for bgroup...egroup, because in



edefsomethingbgroup ABCegroup


bgroup ABCegroup is interpreted as the parameter text, while there is no problem with



edefsomething{iffalse}fi ABCiffalse{fi}


Actually the combination of this with environments allows for a quite interesting hack: You can capture the fully expanded content of an environment in a macro:



newenvironment{EDEF}[1]{xdef#1{iffalse}fi}{iffalse{fi}}
begin{EDEF}ABCD
Something interesting
end{EDEF}


This defines a macro ABCD as the full expansion of Something interesting.






share|improve this answer
























  • Thank you for pointing out the typo! I will edit my question to reflect that.

    – Steven B. Segletes
    Mar 6 '18 at 11:29






  • 1





    Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

    – Steven B. Segletes
    Mar 6 '18 at 11:50






  • 6





    +1 for the EDEF environment. Impressive!

    – Phelype Oleinik
    Mar 6 '18 at 12:24



















10














Perhaps I should add some explanation about the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi hack (note that the intended usage is with the “delimiters” in this order: I never meant to suggest using them in flipped order, that is, ifnum`{=z@fiiffalse}fi ... iffalse{fiifnum`}=z@fi).



Before writing my comment, I had been trying to figure out what the OP was attempting to achieve in connection with @egreg’s answer. I was too lazy to look into the code of the tabstackengine package, nonetheless I got the vague intuition that he was looking for a brace hack to be used to “wrap up” the definition of a command, or of an environment, in such a way that:




  • occurences of & (or cr) tokens inside the argument of the
    command, or the contents of the environment, are “shielded” from
    being interpreted as belonging to an outer alignment, if the
    command or the environment happen to be used in the context of
    an outer alignment;


  • on the other hand, the braces should not be “executed” in the
    stomach, which means that no subgroup, or subformula, will be
    created, thus allowing proper interpretation of math atoms and
    preventing definitions issued inside the command or the environment
    from being regarded as local.



Given these requirements, the hack almost suggested itself. Indeed, consider, for example, the following alternative to @egreg’s suggested patch to the code of tabstackengine:



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fiifnum`}=z@fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
ifnum`{=z@fiiffalse}fi
}
makeatother


Recall that TeX does expand tokens when it is reading alignment entries (contrast this with the case of the alignment preamble). Now, iffalse{fi increments the master counter, even if the brace itself is discarded and is not contributed to the current token list, as documented on p. 385 of The TeXbook; on the other hand, the following ifnum`}=z@fi (which, in general, we need in order to build a definition with properly balanced braces—note that it is not needed in this particular case, we could simply say



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
iffalse}fi
}
makeatother


and it would work fine; note also that, since TeX does not expand tokens in the replacement text, it doesn’t even realize that the } in ifnum`}=z@fi is part of a numeric costant), the following ifnum`}=z@fi, we were saying, leaves the master counter unchanged; so, the net change is +1. Things go similarly for the ifnum`{=z@fiiffalse}fi case, with a net change in the master counter of -1, yet with no brace being actually contributed to the current token list.



Since it has the desired effect on the master counter, the construction is effective in “shielding” inner & tokens from an outer alignment; since no brace actually reaches TeX’s stomach, the construction doesn’t produce a subformula that would interfere with the concatenation of atoms in the current math list, or a subgroup that would keep definitions local.



Finally, it is obvious that the idiom cannot be used to delimit an expanded definition (edef/xdef), since it is meant exactly to behave as “a pair of braces that exist only for the purpose of nesting alignments, and for no other one”.





Addition



It should be noted that the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi pair is, in essence, exactly the pair of “brace-like” idioms that the mhsetup package (invoked by mathtools) defines as the MH_group_align_safe_begin:/MH_group_align_safe_end: pair. Indeed, the definition we find in mhsetup.sty is



def MH_group_align_safe_begin: {iffalse{fiifnum0=`}fi}
def MH_group_align_safe_end: {ifnum0=`{}fi}


which gives the same result, but using fewer tokens in the definition of the closing “brace”. Let us discuss briefly how it works.




  1. When the macros are being defined, the tokens in the replacement text
    are not “executed”, they are just stored away keeping count of {/}
    nested pair; since the replacement text of both macros contains balanced
    {/} pairs, both definitions are correctly carried out.



  2. When TeX is scanning the entry of an alignment, on the other hand,
    tokens are expanded, which means in particular that conditionals
    are evaluated. Now:



    a) for the purpose of deciding when the entry terminates,
    for which only the master counter matters, the evaluation
    of the numeric constants inside the conditionals
    ifnum0=`}fi and ifnum0=`{}fi (constants that are
    evaluated exactly because the conditionals are) have the effect
    documented on p. 385 of The TeXbook; thus
    MH_group_align_safe_begin: increments the master counter,
    while
    MH_group_align_safe_end: decrements it, as desired;



    b) for the purpose of deciding which tokens are forwarded to TeX’s
    stomach, note that, in the above definitions, all braces are
    discarded because they occur in the false branch of a conditional:
    this is true also of the } inside the ifnum0=`{}fi test,
    because the ASCII code of { is not zero!



    In particular, b) shows that there is no need to add a second conditional
    (namely, iffalse ... fi) around the } token in the definition of
    MH_group_align_safe_end:. Unfortunately, a similar trick doesn’t work
    for MH_group_align_safe_begin: (just think of it).




I hope to be able to further improve this answer during Easter vacation (if nobody else has done so by then!).






share|improve this answer





















  • 1





    Thank you for taking the time to add your expertise to the mix.

    – Steven B. Segletes
    Mar 7 '18 at 0:25











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f418621%2funderstanding-brace-hacks%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









19














The fourth case is actually 0110, the 1110 came from a typo in the code:
Your test



E&=mc^2
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}


is the test for the sixth case, it should be



E&=mc^2
+ ifnum0=`{fiblech{A&OK}ifnum0=`}fi


instead.



This leaves {iffalse}fi...iffalse{fi} and bgroup...egroup.
According to the TeXbook, the difference lies in the expanded version of the balance counter.
The balance counter is used for example for macro definitions and we need expansion, so we can construct an additional test:




  1. Can be used to delimit the definition of an edef.


This will fail for bgroup...egroup, because in



edefsomethingbgroup ABCegroup


bgroup ABCegroup is interpreted as the parameter text, while there is no problem with



edefsomething{iffalse}fi ABCiffalse{fi}


Actually the combination of this with environments allows for a quite interesting hack: You can capture the fully expanded content of an environment in a macro:



newenvironment{EDEF}[1]{xdef#1{iffalse}fi}{iffalse{fi}}
begin{EDEF}ABCD
Something interesting
end{EDEF}


This defines a macro ABCD as the full expansion of Something interesting.






share|improve this answer
























  • Thank you for pointing out the typo! I will edit my question to reflect that.

    – Steven B. Segletes
    Mar 6 '18 at 11:29






  • 1





    Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

    – Steven B. Segletes
    Mar 6 '18 at 11:50






  • 6





    +1 for the EDEF environment. Impressive!

    – Phelype Oleinik
    Mar 6 '18 at 12:24
















19














The fourth case is actually 0110, the 1110 came from a typo in the code:
Your test



E&=mc^2
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}


is the test for the sixth case, it should be



E&=mc^2
+ ifnum0=`{fiblech{A&OK}ifnum0=`}fi


instead.



This leaves {iffalse}fi...iffalse{fi} and bgroup...egroup.
According to the TeXbook, the difference lies in the expanded version of the balance counter.
The balance counter is used for example for macro definitions and we need expansion, so we can construct an additional test:




  1. Can be used to delimit the definition of an edef.


This will fail for bgroup...egroup, because in



edefsomethingbgroup ABCegroup


bgroup ABCegroup is interpreted as the parameter text, while there is no problem with



edefsomething{iffalse}fi ABCiffalse{fi}


Actually the combination of this with environments allows for a quite interesting hack: You can capture the fully expanded content of an environment in a macro:



newenvironment{EDEF}[1]{xdef#1{iffalse}fi}{iffalse{fi}}
begin{EDEF}ABCD
Something interesting
end{EDEF}


This defines a macro ABCD as the full expansion of Something interesting.






share|improve this answer
























  • Thank you for pointing out the typo! I will edit my question to reflect that.

    – Steven B. Segletes
    Mar 6 '18 at 11:29






  • 1





    Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

    – Steven B. Segletes
    Mar 6 '18 at 11:50






  • 6





    +1 for the EDEF environment. Impressive!

    – Phelype Oleinik
    Mar 6 '18 at 12:24














19












19








19







The fourth case is actually 0110, the 1110 came from a typo in the code:
Your test



E&=mc^2
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}


is the test for the sixth case, it should be



E&=mc^2
+ ifnum0=`{fiblech{A&OK}ifnum0=`}fi


instead.



This leaves {iffalse}fi...iffalse{fi} and bgroup...egroup.
According to the TeXbook, the difference lies in the expanded version of the balance counter.
The balance counter is used for example for macro definitions and we need expansion, so we can construct an additional test:




  1. Can be used to delimit the definition of an edef.


This will fail for bgroup...egroup, because in



edefsomethingbgroup ABCegroup


bgroup ABCegroup is interpreted as the parameter text, while there is no problem with



edefsomething{iffalse}fi ABCiffalse{fi}


Actually the combination of this with environments allows for a quite interesting hack: You can capture the fully expanded content of an environment in a macro:



newenvironment{EDEF}[1]{xdef#1{iffalse}fi}{iffalse{fi}}
begin{EDEF}ABCD
Something interesting
end{EDEF}


This defines a macro ABCD as the full expansion of Something interesting.






share|improve this answer













The fourth case is actually 0110, the 1110 came from a typo in the code:
Your test



E&=mc^2
+ {ifnum0=`}fiblech{A&OK}ifnum0=`{fi}


is the test for the sixth case, it should be



E&=mc^2
+ ifnum0=`{fiblech{A&OK}ifnum0=`}fi


instead.



This leaves {iffalse}fi...iffalse{fi} and bgroup...egroup.
According to the TeXbook, the difference lies in the expanded version of the balance counter.
The balance counter is used for example for macro definitions and we need expansion, so we can construct an additional test:




  1. Can be used to delimit the definition of an edef.


This will fail for bgroup...egroup, because in



edefsomethingbgroup ABCegroup


bgroup ABCegroup is interpreted as the parameter text, while there is no problem with



edefsomething{iffalse}fi ABCiffalse{fi}


Actually the combination of this with environments allows for a quite interesting hack: You can capture the fully expanded content of an environment in a macro:



newenvironment{EDEF}[1]{xdef#1{iffalse}fi}{iffalse{fi}}
begin{EDEF}ABCD
Something interesting
end{EDEF}


This defines a macro ABCD as the full expansion of Something interesting.







share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 6 '18 at 9:21









Marcel KrügerMarcel Krüger

11.9k11535




11.9k11535













  • Thank you for pointing out the typo! I will edit my question to reflect that.

    – Steven B. Segletes
    Mar 6 '18 at 11:29






  • 1





    Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

    – Steven B. Segletes
    Mar 6 '18 at 11:50






  • 6





    +1 for the EDEF environment. Impressive!

    – Phelype Oleinik
    Mar 6 '18 at 12:24



















  • Thank you for pointing out the typo! I will edit my question to reflect that.

    – Steven B. Segletes
    Mar 6 '18 at 11:29






  • 1





    Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

    – Steven B. Segletes
    Mar 6 '18 at 11:50






  • 6





    +1 for the EDEF environment. Impressive!

    – Phelype Oleinik
    Mar 6 '18 at 12:24

















Thank you for pointing out the typo! I will edit my question to reflect that.

– Steven B. Segletes
Mar 6 '18 at 11:29





Thank you for pointing out the typo! I will edit my question to reflect that.

– Steven B. Segletes
Mar 6 '18 at 11:29




1




1





Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

– Steven B. Segletes
Mar 6 '18 at 11:50





Your answer is really quite thorough. You caught the typo, which resolved the one conundrum, and you developed a test to differentiate what I could not differentiate. Thank you so much for this really nice answer.

– Steven B. Segletes
Mar 6 '18 at 11:50




6




6





+1 for the EDEF environment. Impressive!

– Phelype Oleinik
Mar 6 '18 at 12:24





+1 for the EDEF environment. Impressive!

– Phelype Oleinik
Mar 6 '18 at 12:24











10














Perhaps I should add some explanation about the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi hack (note that the intended usage is with the “delimiters” in this order: I never meant to suggest using them in flipped order, that is, ifnum`{=z@fiiffalse}fi ... iffalse{fiifnum`}=z@fi).



Before writing my comment, I had been trying to figure out what the OP was attempting to achieve in connection with @egreg’s answer. I was too lazy to look into the code of the tabstackengine package, nonetheless I got the vague intuition that he was looking for a brace hack to be used to “wrap up” the definition of a command, or of an environment, in such a way that:




  • occurences of & (or cr) tokens inside the argument of the
    command, or the contents of the environment, are “shielded” from
    being interpreted as belonging to an outer alignment, if the
    command or the environment happen to be used in the context of
    an outer alignment;


  • on the other hand, the braces should not be “executed” in the
    stomach, which means that no subgroup, or subformula, will be
    created, thus allowing proper interpretation of math atoms and
    preventing definitions issued inside the command or the environment
    from being regarded as local.



Given these requirements, the hack almost suggested itself. Indeed, consider, for example, the following alternative to @egreg’s suggested patch to the code of tabstackengine:



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fiifnum`}=z@fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
ifnum`{=z@fiiffalse}fi
}
makeatother


Recall that TeX does expand tokens when it is reading alignment entries (contrast this with the case of the alignment preamble). Now, iffalse{fi increments the master counter, even if the brace itself is discarded and is not contributed to the current token list, as documented on p. 385 of The TeXbook; on the other hand, the following ifnum`}=z@fi (which, in general, we need in order to build a definition with properly balanced braces—note that it is not needed in this particular case, we could simply say



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
iffalse}fi
}
makeatother


and it would work fine; note also that, since TeX does not expand tokens in the replacement text, it doesn’t even realize that the } in ifnum`}=z@fi is part of a numeric costant), the following ifnum`}=z@fi, we were saying, leaves the master counter unchanged; so, the net change is +1. Things go similarly for the ifnum`{=z@fiiffalse}fi case, with a net change in the master counter of -1, yet with no brace being actually contributed to the current token list.



Since it has the desired effect on the master counter, the construction is effective in “shielding” inner & tokens from an outer alignment; since no brace actually reaches TeX’s stomach, the construction doesn’t produce a subformula that would interfere with the concatenation of atoms in the current math list, or a subgroup that would keep definitions local.



Finally, it is obvious that the idiom cannot be used to delimit an expanded definition (edef/xdef), since it is meant exactly to behave as “a pair of braces that exist only for the purpose of nesting alignments, and for no other one”.





Addition



It should be noted that the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi pair is, in essence, exactly the pair of “brace-like” idioms that the mhsetup package (invoked by mathtools) defines as the MH_group_align_safe_begin:/MH_group_align_safe_end: pair. Indeed, the definition we find in mhsetup.sty is



def MH_group_align_safe_begin: {iffalse{fiifnum0=`}fi}
def MH_group_align_safe_end: {ifnum0=`{}fi}


which gives the same result, but using fewer tokens in the definition of the closing “brace”. Let us discuss briefly how it works.




  1. When the macros are being defined, the tokens in the replacement text
    are not “executed”, they are just stored away keeping count of {/}
    nested pair; since the replacement text of both macros contains balanced
    {/} pairs, both definitions are correctly carried out.



  2. When TeX is scanning the entry of an alignment, on the other hand,
    tokens are expanded, which means in particular that conditionals
    are evaluated. Now:



    a) for the purpose of deciding when the entry terminates,
    for which only the master counter matters, the evaluation
    of the numeric constants inside the conditionals
    ifnum0=`}fi and ifnum0=`{}fi (constants that are
    evaluated exactly because the conditionals are) have the effect
    documented on p. 385 of The TeXbook; thus
    MH_group_align_safe_begin: increments the master counter,
    while
    MH_group_align_safe_end: decrements it, as desired;



    b) for the purpose of deciding which tokens are forwarded to TeX’s
    stomach, note that, in the above definitions, all braces are
    discarded because they occur in the false branch of a conditional:
    this is true also of the } inside the ifnum0=`{}fi test,
    because the ASCII code of { is not zero!



    In particular, b) shows that there is no need to add a second conditional
    (namely, iffalse ... fi) around the } token in the definition of
    MH_group_align_safe_end:. Unfortunately, a similar trick doesn’t work
    for MH_group_align_safe_begin: (just think of it).




I hope to be able to further improve this answer during Easter vacation (if nobody else has done so by then!).






share|improve this answer





















  • 1





    Thank you for taking the time to add your expertise to the mix.

    – Steven B. Segletes
    Mar 7 '18 at 0:25
















10














Perhaps I should add some explanation about the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi hack (note that the intended usage is with the “delimiters” in this order: I never meant to suggest using them in flipped order, that is, ifnum`{=z@fiiffalse}fi ... iffalse{fiifnum`}=z@fi).



Before writing my comment, I had been trying to figure out what the OP was attempting to achieve in connection with @egreg’s answer. I was too lazy to look into the code of the tabstackengine package, nonetheless I got the vague intuition that he was looking for a brace hack to be used to “wrap up” the definition of a command, or of an environment, in such a way that:




  • occurences of & (or cr) tokens inside the argument of the
    command, or the contents of the environment, are “shielded” from
    being interpreted as belonging to an outer alignment, if the
    command or the environment happen to be used in the context of
    an outer alignment;


  • on the other hand, the braces should not be “executed” in the
    stomach, which means that no subgroup, or subformula, will be
    created, thus allowing proper interpretation of math atoms and
    preventing definitions issued inside the command or the environment
    from being regarded as local.



Given these requirements, the hack almost suggested itself. Indeed, consider, for example, the following alternative to @egreg’s suggested patch to the code of tabstackengine:



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fiifnum`}=z@fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
ifnum`{=z@fiiffalse}fi
}
makeatother


Recall that TeX does expand tokens when it is reading alignment entries (contrast this with the case of the alignment preamble). Now, iffalse{fi increments the master counter, even if the brace itself is discarded and is not contributed to the current token list, as documented on p. 385 of The TeXbook; on the other hand, the following ifnum`}=z@fi (which, in general, we need in order to build a definition with properly balanced braces—note that it is not needed in this particular case, we could simply say



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
iffalse}fi
}
makeatother


and it would work fine; note also that, since TeX does not expand tokens in the replacement text, it doesn’t even realize that the } in ifnum`}=z@fi is part of a numeric costant), the following ifnum`}=z@fi, we were saying, leaves the master counter unchanged; so, the net change is +1. Things go similarly for the ifnum`{=z@fiiffalse}fi case, with a net change in the master counter of -1, yet with no brace being actually contributed to the current token list.



Since it has the desired effect on the master counter, the construction is effective in “shielding” inner & tokens from an outer alignment; since no brace actually reaches TeX’s stomach, the construction doesn’t produce a subformula that would interfere with the concatenation of atoms in the current math list, or a subgroup that would keep definitions local.



Finally, it is obvious that the idiom cannot be used to delimit an expanded definition (edef/xdef), since it is meant exactly to behave as “a pair of braces that exist only for the purpose of nesting alignments, and for no other one”.





Addition



It should be noted that the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi pair is, in essence, exactly the pair of “brace-like” idioms that the mhsetup package (invoked by mathtools) defines as the MH_group_align_safe_begin:/MH_group_align_safe_end: pair. Indeed, the definition we find in mhsetup.sty is



def MH_group_align_safe_begin: {iffalse{fiifnum0=`}fi}
def MH_group_align_safe_end: {ifnum0=`{}fi}


which gives the same result, but using fewer tokens in the definition of the closing “brace”. Let us discuss briefly how it works.




  1. When the macros are being defined, the tokens in the replacement text
    are not “executed”, they are just stored away keeping count of {/}
    nested pair; since the replacement text of both macros contains balanced
    {/} pairs, both definitions are correctly carried out.



  2. When TeX is scanning the entry of an alignment, on the other hand,
    tokens are expanded, which means in particular that conditionals
    are evaluated. Now:



    a) for the purpose of deciding when the entry terminates,
    for which only the master counter matters, the evaluation
    of the numeric constants inside the conditionals
    ifnum0=`}fi and ifnum0=`{}fi (constants that are
    evaluated exactly because the conditionals are) have the effect
    documented on p. 385 of The TeXbook; thus
    MH_group_align_safe_begin: increments the master counter,
    while
    MH_group_align_safe_end: decrements it, as desired;



    b) for the purpose of deciding which tokens are forwarded to TeX’s
    stomach, note that, in the above definitions, all braces are
    discarded because they occur in the false branch of a conditional:
    this is true also of the } inside the ifnum0=`{}fi test,
    because the ASCII code of { is not zero!



    In particular, b) shows that there is no need to add a second conditional
    (namely, iffalse ... fi) around the } token in the definition of
    MH_group_align_safe_end:. Unfortunately, a similar trick doesn’t work
    for MH_group_align_safe_begin: (just think of it).




I hope to be able to further improve this answer during Easter vacation (if nobody else has done so by then!).






share|improve this answer





















  • 1





    Thank you for taking the time to add your expertise to the mix.

    – Steven B. Segletes
    Mar 7 '18 at 0:25














10












10








10







Perhaps I should add some explanation about the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi hack (note that the intended usage is with the “delimiters” in this order: I never meant to suggest using them in flipped order, that is, ifnum`{=z@fiiffalse}fi ... iffalse{fiifnum`}=z@fi).



Before writing my comment, I had been trying to figure out what the OP was attempting to achieve in connection with @egreg’s answer. I was too lazy to look into the code of the tabstackengine package, nonetheless I got the vague intuition that he was looking for a brace hack to be used to “wrap up” the definition of a command, or of an environment, in such a way that:




  • occurences of & (or cr) tokens inside the argument of the
    command, or the contents of the environment, are “shielded” from
    being interpreted as belonging to an outer alignment, if the
    command or the environment happen to be used in the context of
    an outer alignment;


  • on the other hand, the braces should not be “executed” in the
    stomach, which means that no subgroup, or subformula, will be
    created, thus allowing proper interpretation of math atoms and
    preventing definitions issued inside the command or the environment
    from being regarded as local.



Given these requirements, the hack almost suggested itself. Indeed, consider, for example, the following alternative to @egreg’s suggested patch to the code of tabstackengine:



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fiifnum`}=z@fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
ifnum`{=z@fiiffalse}fi
}
makeatother


Recall that TeX does expand tokens when it is reading alignment entries (contrast this with the case of the alignment preamble). Now, iffalse{fi increments the master counter, even if the brace itself is discarded and is not contributed to the current token list, as documented on p. 385 of The TeXbook; on the other hand, the following ifnum`}=z@fi (which, in general, we need in order to build a definition with properly balanced braces—note that it is not needed in this particular case, we could simply say



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
iffalse}fi
}
makeatother


and it would work fine; note also that, since TeX does not expand tokens in the replacement text, it doesn’t even realize that the } in ifnum`}=z@fi is part of a numeric costant), the following ifnum`}=z@fi, we were saying, leaves the master counter unchanged; so, the net change is +1. Things go similarly for the ifnum`{=z@fiiffalse}fi case, with a net change in the master counter of -1, yet with no brace being actually contributed to the current token list.



Since it has the desired effect on the master counter, the construction is effective in “shielding” inner & tokens from an outer alignment; since no brace actually reaches TeX’s stomach, the construction doesn’t produce a subformula that would interfere with the concatenation of atoms in the current math list, or a subgroup that would keep definitions local.



Finally, it is obvious that the idiom cannot be used to delimit an expanded definition (edef/xdef), since it is meant exactly to behave as “a pair of braces that exist only for the purpose of nesting alignments, and for no other one”.





Addition



It should be noted that the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi pair is, in essence, exactly the pair of “brace-like” idioms that the mhsetup package (invoked by mathtools) defines as the MH_group_align_safe_begin:/MH_group_align_safe_end: pair. Indeed, the definition we find in mhsetup.sty is



def MH_group_align_safe_begin: {iffalse{fiifnum0=`}fi}
def MH_group_align_safe_end: {ifnum0=`{}fi}


which gives the same result, but using fewer tokens in the definition of the closing “brace”. Let us discuss briefly how it works.




  1. When the macros are being defined, the tokens in the replacement text
    are not “executed”, they are just stored away keeping count of {/}
    nested pair; since the replacement text of both macros contains balanced
    {/} pairs, both definitions are correctly carried out.



  2. When TeX is scanning the entry of an alignment, on the other hand,
    tokens are expanded, which means in particular that conditionals
    are evaluated. Now:



    a) for the purpose of deciding when the entry terminates,
    for which only the master counter matters, the evaluation
    of the numeric constants inside the conditionals
    ifnum0=`}fi and ifnum0=`{}fi (constants that are
    evaluated exactly because the conditionals are) have the effect
    documented on p. 385 of The TeXbook; thus
    MH_group_align_safe_begin: increments the master counter,
    while
    MH_group_align_safe_end: decrements it, as desired;



    b) for the purpose of deciding which tokens are forwarded to TeX’s
    stomach, note that, in the above definitions, all braces are
    discarded because they occur in the false branch of a conditional:
    this is true also of the } inside the ifnum0=`{}fi test,
    because the ASCII code of { is not zero!



    In particular, b) shows that there is no need to add a second conditional
    (namely, iffalse ... fi) around the } token in the definition of
    MH_group_align_safe_end:. Unfortunately, a similar trick doesn’t work
    for MH_group_align_safe_begin: (just think of it).




I hope to be able to further improve this answer during Easter vacation (if nobody else has done so by then!).






share|improve this answer















Perhaps I should add some explanation about the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi hack (note that the intended usage is with the “delimiters” in this order: I never meant to suggest using them in flipped order, that is, ifnum`{=z@fiiffalse}fi ... iffalse{fiifnum`}=z@fi).



Before writing my comment, I had been trying to figure out what the OP was attempting to achieve in connection with @egreg’s answer. I was too lazy to look into the code of the tabstackengine package, nonetheless I got the vague intuition that he was looking for a brace hack to be used to “wrap up” the definition of a command, or of an environment, in such a way that:




  • occurences of & (or cr) tokens inside the argument of the
    command, or the contents of the environment, are “shielded” from
    being interpreted as belonging to an outer alignment, if the
    command or the environment happen to be used in the context of
    an outer alignment;


  • on the other hand, the braces should not be “executed” in the
    stomach, which means that no subgroup, or subformula, will be
    created, thus allowing proper interpretation of math atoms and
    preventing definitions issued inside the command or the environment
    from being regarded as local.



Given these requirements, the hack almost suggested itself. Indeed, consider, for example, the following alternative to @egreg’s suggested patch to the code of tabstackengine:



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fiifnum`}=z@fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
ifnum`{=z@fiiffalse}fi
}
makeatother


Recall that TeX does expand tokens when it is reading alignment entries (contrast this with the case of the alignment preamble). Now, iffalse{fi increments the master counter, even if the brace itself is discarded and is not contributed to the current token list, as documented on p. 385 of The TeXbook; on the other hand, the following ifnum`}=z@fi (which, in general, we need in order to build a definition with properly balanced braces—note that it is not needed in this particular case, we could simply say



makeatletter
renewcommandensureTABstackMath[1]{%
iffalse{fi
letsv@TABmodeTAB@delimTABstackMath#1letTAB@delimsv@TABmode
iffalse}fi
}
makeatother


and it would work fine; note also that, since TeX does not expand tokens in the replacement text, it doesn’t even realize that the } in ifnum`}=z@fi is part of a numeric costant), the following ifnum`}=z@fi, we were saying, leaves the master counter unchanged; so, the net change is +1. Things go similarly for the ifnum`{=z@fiiffalse}fi case, with a net change in the master counter of -1, yet with no brace being actually contributed to the current token list.



Since it has the desired effect on the master counter, the construction is effective in “shielding” inner & tokens from an outer alignment; since no brace actually reaches TeX’s stomach, the construction doesn’t produce a subformula that would interfere with the concatenation of atoms in the current math list, or a subgroup that would keep definitions local.



Finally, it is obvious that the idiom cannot be used to delimit an expanded definition (edef/xdef), since it is meant exactly to behave as “a pair of braces that exist only for the purpose of nesting alignments, and for no other one”.





Addition



It should be noted that the iffalse{fiifnum`}=z@fi ... ifnum`{=z@fiiffalse}fi pair is, in essence, exactly the pair of “brace-like” idioms that the mhsetup package (invoked by mathtools) defines as the MH_group_align_safe_begin:/MH_group_align_safe_end: pair. Indeed, the definition we find in mhsetup.sty is



def MH_group_align_safe_begin: {iffalse{fiifnum0=`}fi}
def MH_group_align_safe_end: {ifnum0=`{}fi}


which gives the same result, but using fewer tokens in the definition of the closing “brace”. Let us discuss briefly how it works.




  1. When the macros are being defined, the tokens in the replacement text
    are not “executed”, they are just stored away keeping count of {/}
    nested pair; since the replacement text of both macros contains balanced
    {/} pairs, both definitions are correctly carried out.



  2. When TeX is scanning the entry of an alignment, on the other hand,
    tokens are expanded, which means in particular that conditionals
    are evaluated. Now:



    a) for the purpose of deciding when the entry terminates,
    for which only the master counter matters, the evaluation
    of the numeric constants inside the conditionals
    ifnum0=`}fi and ifnum0=`{}fi (constants that are
    evaluated exactly because the conditionals are) have the effect
    documented on p. 385 of The TeXbook; thus
    MH_group_align_safe_begin: increments the master counter,
    while
    MH_group_align_safe_end: decrements it, as desired;



    b) for the purpose of deciding which tokens are forwarded to TeX’s
    stomach, note that, in the above definitions, all braces are
    discarded because they occur in the false branch of a conditional:
    this is true also of the } inside the ifnum0=`{}fi test,
    because the ASCII code of { is not zero!



    In particular, b) shows that there is no need to add a second conditional
    (namely, iffalse ... fi) around the } token in the definition of
    MH_group_align_safe_end:. Unfortunately, a similar trick doesn’t work
    for MH_group_align_safe_begin: (just think of it).




I hope to be able to further improve this answer during Easter vacation (if nobody else has done so by then!).







share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 10 at 0:59

























answered Mar 6 '18 at 21:27









GuMGuM

16.6k2457




16.6k2457








  • 1





    Thank you for taking the time to add your expertise to the mix.

    – Steven B. Segletes
    Mar 7 '18 at 0:25














  • 1





    Thank you for taking the time to add your expertise to the mix.

    – Steven B. Segletes
    Mar 7 '18 at 0:25








1




1





Thank you for taking the time to add your expertise to the mix.

– Steven B. Segletes
Mar 7 '18 at 0:25





Thank you for taking the time to add your expertise to the mix.

– Steven B. Segletes
Mar 7 '18 at 0:25


















draft saved

draft discarded




















































Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f418621%2funderstanding-brace-hacks%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to change which sound is reproduced for terminal bell?

Can I use Tabulator js library in my java Spring + Thymeleaf project?

Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents