我正在尝试更好地理解 brace hacks。egreg 的回答引起了我的注意,eqnarray 和 tabstackengine 之间的冲突,tabstackengine
无法保护内部对齐组的问题可以通过使用括号 hack 来解决。David Carlisle 向我推荐了 TeXbook,我在第 385 页找到了相关描述。
现在 egreg 使用的那个与第 385 页上的相似但不同。下面我总结了 Knuth 给出的 4 个,并根据 egreg 的回答添加了另外 2 个,关于它们在扩展时和扩展之前如何影响主计数器和平衡计数器:
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
我意识到除了对齐组之外,大括号类型还会影响数学二元/一元类别与相邻原子的通信方式,它们可以限制定义数据的范围,并且有些可以在没有相应的[平衡]大括号的情况下在宏/环境定义中使用,也可以不使用它。
为此,我建立了一个 MWE 来测试上面显示的 6 种支架类型以及\begingroup...\endgroup
,看看它们的表现并对每个结果进行评分:
% BRACE HACK TESTING/LEARNING
%
\documentclass{article}
\usepackage{amsmath}
\usepackage[margin=3cm]{geometry}
\newenvironment{QQQ}{}{}
\def\blech#1{\blechaux#1\relax}
\def\blechaux#1\relax{#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
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|{...}|\hfill Grade 1000
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ {\blech{A&OK}}
\end{aligned}$\hfill
$A{=}B$\hfill${\def\Q{XYZ}}\meaning\Q$
%\renewenvironment{QQQ}{{\catcode`&=12 }{}}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}%\bgroup\blech{A&OK}\egroup
\end{aligned}$\hfill
$A\bgroup=\egroup B$\hfill$\bgroup\def\Q{XYZ}\egroup\meaning\Q$
\renewenvironment{QQQ}{\bgroup\catcode`&=12 }{\egroup}
\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|\iffalse{\fi...\iffalse}\fi|\hfill Grade 1110
$\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\def\Q{XYZ}\iffalse}\fi\meaning\Q$
%\renewenvironment{QQQ}{\iffalse{\fi\catcode`&=12 }{\iffalse}\fi}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|\ifnum0=`{\fi...\ifnum0=`}\fi|\hfill Grade 0110
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ \textrm{BAD ALIGNMENT}%\ifnum0=`{\fi\blech{A&OK}\ifnum0=`}\fi
\end{aligned}$\hfill
$A\ifnum0=`{\fi=\ifnum0=`}\fi B$\hfill$\ifnum0=`{\fi\def\Q{XYZ}\ifnum0=`}\fi\meaning\Q$
%\renewenvironment{QQQ}{\ifnum0=`{\fi\catcode`&=12 }{\ifnum0=`}\fi}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|{\iffalse}\fi...\iffalse{\fi}|\hfill Grade 0001
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ \textrm{BAD ALIGNMENT}% {\iffalse}\fi\blech{A&OK}\iffalse{\fi}
\end{aligned}$\hfill
$A{\iffalse}\fi=\iffalse{\fi} B$\hfill${\iffalse}\fi\def\Q{XYZ}\iffalse{\fi}\meaning\Q$
\renewenvironment{QQQ}{{\iffalse}\fi\catcode`&=12 }{\iffalse{\fi}}
\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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=`}\fi\blech{A&OK}\ifnum0=`{\fi}
\end{aligned}$\hfill
$A{\ifnum0=`}\fi=\ifnum0=`{\fi}B$\hfill${\ifnum0=`}\fi\def\Q{XYZ}\ifnum0=`{\fi}\meaning\Q$
\renewenvironment{QQQ}{{\ifnum0=`}\fi\catcode`&=12 }{\ifnum0=`{\fi}}
\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}%\begingroup\blech{A&OK}\endgroup}\meaning \Q
\end{aligned}$\hfill
$A\begingroup=\endgroup B$\hfill$\begingroup\def\Q{XYZ}\endgroup\meaning\Q$
\renewenvironment{QQQ}{\begingroup\catcode`&=12 }{\endgroup}
\begin{QQQ}&&&\end{QQQ}
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
成绩是一个 4 位数字,每个连续的数字描述对 4 个问题的“做或不做”:
A/OK
如果括号方法保护内部对齐组( vs.BAD ALIGNMENT
),则获取 1如果周围的数学原子可以通过边界传达它们的存在,则得到 1(
A = B
与A=B
)如果内部宏定义在分组之外保留,则获取 1(
macro:-> XYZ
与undefined
)如果不平衡版本的大括号类型可以在环境 (
&&&
vs.BAD ENV. DEFINITION
) 中使用,则获取 1。
为了完整起见,我想我应该指出,任何支撑(未在我的 MWE 中执行)将获得 的分数0111
。
这一切对我来说都非常有启发性,但我原本以为肯定还有更多差异(要执行的测试)可以区分我所忽略的这些方法。然而,这种想法是基于 Marcel 发现并指出的我代码中的一个拼写错误。尽管如此,可能还有更多测试可以进一步区分结果。此外,我的结果(“等级”)与 Knuth 的描述不同,后者用对主计数器和平衡计数器的影响来描述差异,无论是输入的扩展状态还是未扩展状态。
我还注意到,我有限的测试表明 的\bgroup...\egroup
行为方式与 完全相同{\iffalse}\fi...\iffalse{\fi}
。事实确实如此吗?
所以问题很简单,是否可以进行其他测试来进一步区分我的 MWE 中显示的七种不同支撑技术的行为?是否有其他支撑技巧可以为问题带来进一步的细微差别?
tabstackengine
附言:我今天提交了修订版ctan.org
,修复了内部对齐组问题并提供了一些新功能。
结果,感谢 MARCEL 的回答和 GuM 的建议
感谢 Marcel 的回答,我们了解到了两件重要的事情:
我原来的问题中有一个拼写错误,这导致了我的一个误解(在不影响 Marcel 的回答的情况下,我编辑了原始问题来修复它,因为拼写错误通常会导致很糟糕的问题)
添加了第五个测试,以进一步区分等级:是否可以使用大括号来界定
\edef
。
此外,GuM 还提出了两种可能的支撑方法,其中一种方法被证明是非常成功的:\iffalse{\fi\ifnum0=‘}\fi...\ifnum0=‘{\fi\iffalse}\fi
。我已将其添加到我的列表中。
我在下面展示了更新后的结果,并包括“没有任何分隔符”的控制情况。通过这第五次测试,结果完全清楚,表明没有两个括号技巧在 5 次测试中表现相同,并且进一步表明有些是互补(相反)的支撑条件:
无分隔符和括号分隔符的情况
{...}
是互补的,等级分别为01110
和10001
。\iffalse{\fi...\iffalse}\fi
和的情况{\iffalse}\fi...\iffalse{\fi}
是互补的,等级分别为11100
和00011
。\ifnum0=‘{\fi...\ifnum0=‘}\fi
和的情况{\ifnum0=‘}\fi...\ifnum0=‘{\fi}
是互补的,等级分别为01100
和10011
。其余两种情况
\bgroup...\egroup
和\begingroup...\endgroup
类似,只是众所周知的区别在于后者将允许数学类跨越边界看到相邻的数学原子。它们各自的分数分别为00010
和01010
。Gum 建议的括号破解具有最全面的得分
11110
,这意味着它可以保护/隔离内部对齐组,提供跨边界的数学原子知识,保留跨外部边界的内部定义数据,并在开始/结束环境定义中用作打开/关闭对。它唯一的缺点是它不能界定\edef
。
也许马塞尔在他的回答中最酷的洞察力是,{\iffalse}\fi...\iffalse{\fi}
大括号黑客可以在整个环境定义中使用,以便捕获环境的完全扩展的内容;一个非常独特的见解。
更新后的 MWE 整合了我在这里学到的所有知识:
% BRACE HACK TESTING/LEARNING
%
\documentclass{article}
\usepackage{amsmath}
\usepackage[margin=3cm,top=2cm,bottom=2cm]{geometry}
\newenvironment{QQQ}{}{}
\def\blech#1{\blechaux#1\relax}
\def\blechaux#1\relax{#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.
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|...| (absence of delimiters)\hfill Grade 01110
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|{...}|\hfill Grade 10001
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ {\blech{A&OK}}
\end{aligned}$\hfill
$A{=}B$\hfill${\def\Q{XYZ}}\meaning\Q$
%\renewenvironment{QQQ}{{\catcode`&=12 }{}}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\hfill\edef\QQ{\today}[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}%\bgroup\blech{A&OK}\egroup
\end{aligned}$\hfill
$A\bgroup=\egroup B$\hfill$\bgroup\def\Q{XYZ}\egroup\meaning\Q$
\renewenvironment{QQQ}{\bgroup\catcode`&=12 }{\egroup}
\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\bgroup\today\egroup[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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\def\Q{XYZ}\iffalse}\fi\meaning\Q$
%\renewenvironment{QQQ}{\iffalse{\fi\catcode`&=12 }{\iffalse}\fi}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\iffalse{\fi\today\iffalse}\fi[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|\ifnum0=`{\fi...\ifnum0=`}\fi|\hfill Grade 01100
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ \textrm{BAD ALIGNMENT}%\ifnum0=`{\fi\blech{A&OK}\ifnum0=`}\fi
\end{aligned}$\hfill
$A\ifnum0=`{\fi=\ifnum0=`}\fi B$\hfill$\ifnum0=`{\fi\def\Q{XYZ}\ifnum0=`}\fi\meaning\Q$
%\renewenvironment{QQQ}{\ifnum0=`{\fi\catcode`&=12 }{\ifnum0=`}\fi}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\ifnum0=`{\fi\today\ifnum0=`}\fi[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|{\iffalse}\fi...\iffalse{\fi}|\hfill Grade 00011
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ \textrm{BAD ALIGNMENT}% {\iffalse}\fi\blech{A&OK}\iffalse{\fi}
\end{aligned}$\hfill
$A{\iffalse}\fi=\iffalse{\fi} B$\hfill${\iffalse}\fi\def\Q{XYZ}\iffalse{\fi}\meaning\Q$
\renewenvironment{QQQ}{{\iffalse}\fi\catcode`&=12 }{\iffalse{\fi}}
\begin{QQQ}&&&\end{QQQ}
\hfill\edef\QQ{\iffalse}\fi\today\iffalse{\fi}[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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=`}\fi\blech{A&OK}\ifnum0=`{\fi}
\end{aligned}$\hfill
$A{\ifnum0=`}\fi=\ifnum0=`{\fi}B$\hfill${\ifnum0=`}\fi\def\Q{XYZ}\ifnum0=`{\fi}\meaning\Q$
\renewenvironment{QQQ}{{\ifnum0=`}\fi\catcode`&=12 }{\ifnum0=`{\fi}}
\begin{QQQ}&&&\end{QQQ}
\hfill\edef\QQ{\ifnum0=`}\fi\today\ifnum0=`{\fi}[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}%\begingroup\blech{A&OK}\endgroup}
\end{aligned}$\hfill
$A\begingroup=\endgroup B$\hfill$\begingroup\def\Q{XYZ}\endgroup\meaning\Q$
\renewenvironment{QQQ}{\begingroup\catcode`&=12 }{\endgroup}
\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\begingroup\today\endgroup[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|\iffalse{\fi\ifnum0=`}\fi...\ifnum0=`{\fi\iffalse}\fi|\hfill
Grade 11110
$\begin{aligned}
y&=mx + b\\
E&=mc^2
+ \iffalse{\fi\ifnum0=`}\fi\blech{A&OK}\ifnum0=`{\fi\iffalse}\fi
\end{aligned}$\hfill
$A\iffalse{\fi\ifnum0=`}\fi=\ifnum0=`{\fi\iffalse}\fi B$
\hfill$\iffalse{\fi\ifnum0=`}\fi\def\Q{XYZ}\ifnum0=`{\fi\iffalse}\fi\meaning\Q$
\renewenvironment{QQQ}{\iffalse{\fi\ifnum0=`}\fi\catcode`&=12 }{\ifnum0=`{\fi\iffalse}\fi}
\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\iffalse{\fi\ifnum0=`}\fi\today\ifnum0=`{\fi\iffalse}\fi[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\clearpage
{\LARGE\bfseries 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.
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\bullet$Case \verb|\ifnum0=`{\fi\iffalse}\fi...\iffalse{\fi\ifnum0=`}\fi|\hfill
Grade 01110
$\begin{aligned}
y&=mx + b\\
E&=mc^2
% DOES NOT PROTECT INNER ALIGNMENT TAB
+ \textrm{BAD ALIGNMENT}%\ifnum0=`{\fi\iffalse}\fi\blech{A&OK}\iffalse{\fi\ifnum0=`}\fi
\end{aligned}$\hfill
$A\ifnum0=`{\fi\iffalse}\fi=\iffalse{\fi\ifnum0=`}\fi B$
\hfill$\ifnum0=`{\fi\iffalse}\fi\def\Q{XYZ}\iffalse{\fi\ifnum0=`}\fi\meaning\Q$
\renewenvironment{QQQ}{\ifnum0=`{\fi\iffalse}\fi\catcode`&=12 }{\iffalse{\fi\ifnum0=`}\fi}
\begin{QQQ}&&&\end{QQQ}
\hfill CAN'T EDEF%\edef\QQ\ifnum0=`{\fi\iffalse}\fi\today\iffalse{\fi\ifnum0=`}\fi[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.''
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}\def\Q{XYZ}{\iffalse}\fi}\meaning\Q$
%\renewenvironment{QQQ}{{\iffalse{\fi}\catcode`&=12 }{{\iffalse}\fi}}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\hfill\edef\QQ{\iffalse{\fi}executed, not \verb|\edef|ed{\iffalse}\fi}[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$\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}\def\Q{XYZ}{\ifnum0=`}\fi}\meaning\Q$
%\renewenvironment{QQQ}{{\ifnum0=`{\fi}\catcode`&=12 }{{\ifnum0=`}\fi}}
BAD ENV. DEFINITION%\begin{QQQ}&&&\end{QQQ}
\hfill\edef\QQ{\ifnum0=`{\fi}executed, not \verb|\edef|ed{\ifnum0=`}\fi}[\QQ]
\noindent\hrulefill%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
更新后的兑换表如下:
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{\fi\ifnum0=`}\fi 1 0 0 0 (GuM suggestion)
我的 5 位数成绩和此计数器表之间可以建立一些关联:
为了获得第一位数字 1 的等级(保护/隔离内部对齐组的能力),扩展主计数器必须增加 1。
为了在第 4 位数字中获得 1 的等级(能够在环境的开始/结束时用作打开/关闭对),未扩展余额(或主)计数器不得增加(其值为 0)。
为了给 提供分隔符
\edef
,扩展余额计数器必须增加 1。
与计数器表无关,但从评分结果(不包括\begingroup...\endgroup
自成一类的)来看,数字 2 和 3(跨边界的数学原子知识和内部定义数据的保存)的等级为 1,只有在没有无条件的{...}
或的出现\bgroup...\egroup
。
感谢您忍受这个延伸的问题!
答案1
第四种情况实际上是 0110,1110 来自代码中的拼写错误:你的测试
E&=mc^2
+ {\ifnum0=`}\fi\blech{A&OK}\ifnum0=`{\fi}
是第六种情况的测试,应该是
E&=mc^2
+ \ifnum0=`{\fi\blech{A&OK}\ifnum0=`}\fi
反而。
这样就剩下{\iffalse}\fi...\iffalse{\fi}
和了\bgroup...\egroup
。根据 TeXbook,区别在于余额计数器的扩展版本。余额计数器用于宏定义,我们需要扩展,因此我们可以构建一个额外的测试:
- 可用于界定 的定义
\edef
。
这将失败\bgroup...\egroup
,因为
\edef\something\bgroup ABC\egroup
\bgroup ABC\egroup
被解释为参数文本,而
\edef\something{\iffalse}\fi ABC\iffalse{\fi}
实际上,将其与环境相结合可以实现一个非常有趣的黑客攻击:您可以在宏中捕获环境的完全扩展内容:
\newenvironment{EDEF}[1]{\xdef#1{\iffalse}\fi}{\iffalse{\fi}}
\begin{EDEF}\ABCD
Something interesting
\end{EDEF}
这将宏定义\ABCD
为 的完整展开Something interesting
。
答案2
也许我应该添加一些关于\iffalse{\fi\ifnum`}=\z@\fi ... ifnum`{=\z@\fi\iffalse}\fi
黑客的解释(请注意,预期用法是按此顺序使用“分隔符”:我从来没有打算建议以翻转的顺序使用它们,即ifnum`{=\z@\fi\iffalse}\fi ... \iffalse{\fi\ifnum`}=\z@\fi
)。
在发表评论之前,我一直在想,原帖作者想要通过@egreg 的回答。我懒得去看tabstackengine
包的代码,尽管如此,我还是隐约感觉到他在寻找一个括号 hack,用来“包装”命令或环境的定义,这样:
&
如果命令或环境恰好在外部对齐的上下文中使用,则命令参数或环境内容中的(或) 标记的出现\cr
将被“屏蔽”,而不会被解释为属于外部对齐;另一方面,括号不应该在胃中“执行”,这意味着不会创建任何子组或子公式,从而允许正确解释数学原子并防止在命令或环境内部发出的定义被视为本地的。
鉴于这些要求,黑客几乎不费吹灰之力。事实上,例如,请考虑以下 @egreg 建议的 代码补丁的替代方案tabstackengine
:
\makeatletter
\renewcommand\ensureTABstackMath[1]{%
\iffalse{\fi\ifnum`}=\z@\fi
\let\sv@TABmode\TAB@delim\TABstackMath#1\let\TAB@delim\sv@TABmode
\ifnum`{=\z@\fi\iffalse}\fi
}
\makeatother
回想一下,TeX 在读取对齐条目时会扩展标记(与对齐前言的情况形成对比)。现在,\iffalse{\fi
即使括号本身被丢弃并且没有添加到当前标记列表中,也会增加主计数器,如第 385 页所述TeXbook;另一方面,以下\ifnum`}=\z@\fi
(其中,一般来说,我们需要建立一个具有正确平衡括号的定义——注意它是不是在这个特殊情况下,我们可以简单地说
\makeatletter
\renewcommand\ensureTABstackMath[1]{%
\iffalse{\fi
\let\sv@TABmode\TAB@delim\TABstackMath#1\let\TAB@delim\sv@TABmode
\iffalse}\fi
}
\makeatother
并且它会正常工作;还请注意,由于 TeX 不会扩展替换文本中的标记,因此它甚至没有意识到 in}
是\ifnum`}=\z@\fi
数字常数的一部分),\ifnum`}=\z@\fi
我们说,以下 不会改变主计数器;因此,净变化为 +1。对于ifnum`{=\z@\fi\iffalse}\fi
主计数器的净变化为 -1 的情况,情况也类似,但实际上没有括号被贡献到当前标记列表中。
由于它对主计数器具有预期的效果,因此该构造可有效地将内部&
标记与外部对齐“屏蔽”在一起;由于没有大括号实际上到达 TeX 的胃部,因此该构造不会产生会干扰当前数学列表中原子连接的子公式,也不会产生会保持定义局部的子组。
最后,很明显这个习语不能用来界定扩展定义(\edef
/ \xdef
),因为它的行为恰恰相当于“一对括号,其存在的目的仅仅是为了嵌套对齐,而不用于其他目的”。
添加
需要注意的\iffalse{\fi\ifnum`}=\z@\fi ... \ifnum`{=\z@\fi\iffalse}\fi
是,在本质上mhsetup
,正是包(由 调用mathtools
)定义为\MH_group_align_safe_begin:
/对的“括号式”习语对\MH_group_align_safe_end:
。事实上,我们在 中找到的定义mhsetup.sty
是
\def \MH_group_align_safe_begin: {\iffalse{\fi\ifnum0=`}\fi}
\def \MH_group_align_safe_end: {\ifnum0=`{}\fi}
其结果相同,但在结束“括号”的定义中使用更少的标记。让我们简单讨论一下它的工作原理。
当定义宏时,替换文本中的标记不会被“执行”,它们只是被存储起来以保持
{
/}
嵌套对的数量;由于两个宏的替换文本都包含平衡的{
/}
对,因此两个定义都得到正确执行。另一方面,当 TeX 扫描对齐条目时,标记是扩展,这特别意味着条件被评估。现在:
a) 为了决定条目何时终止,只有主计数器才重要,条件语句中的数字常量
\ifnum0=`}\fi
和\ifnum0=`{}\fi
(正是因为条件语句而被评估的常量)的评估具有第 385 页中记录的效果TeXbook;从而 根据需要\MH_group_align_safe_begin:
增加主计数器,同时 减少主计数器;\MH_group_align_safe_end:
b) 为了决定将哪些 token 转发到 TeX 的胃中,请注意,在上述定义中,全部括号被丢弃,因为它们出现在条件的错误分支中:这对于 测试
}
内部的也是如此\ifnum0=`{}\fi
,因为的 ASCII 码{
不是零!具体来说,b) 表明没有必要 在 的定义中在标记
\iffalse ... \fi
周围添加第二个条件(即 )。不幸的是,类似的技巧对 不起作用(想想看)。}
\MH_group_align_safe_end:
\MH_group_align_safe_begin:
我希望能够在复活节假期期间进一步完善这个答案(如果到那时还没有其他人这样做的话!)。