在嵌套的 if 语句中重新定义 \or 形式?

在嵌套的 if 语句中重新定义 \or 形式?

\or重新定义使其呈现为数学模式显然是个坏主意\lor。然而,在尝试的过程中,我遇到了两个问题,我想更好地理解它们。我遵循了以下方法12

\let\@oldor\or
\def\or{\ifmmode\lor\else\expandafter\@oldor\fi}

然而,将其移到另一个 if 语句之后(检查封装选项覆盖\or)它停止工作。相反,我得到了! Extra \or.错误。

偶然间,我发现当我尝试\verb|\or|在脚注中使用时也会遇到同样的错误(背面)

有没有可能我可以重写\def不带 expandafter 的代码,以便它可以在任何地方工作,无论嵌套了多少个 if 语句?

答案1

总结

你无法重新定义\or

较长的答案

考虑这个简单的 TeX 示例:

\let\originalor\or
\def\or{\ifmmode\lor\else\expandafter\originalor\fi}

$a\or b$ (works)

\ifcase1
  0\or
  1\or
  2\else
  BUMMER\fi

\let\or\originalor

\ifcase1
  0\or
  1\or
  2\else
  BUMMER\fi

\bye

猜猜这两个\ifcase语句会给出什么结果。是的,第一个语句的结果是“BUMMER”,而另一个语句\or恢复了其原始含义,得到了预期的 1。

为什么会这样?为了跳过这些情况,TeX需求看到原始 \or(将控制序列传递给原语\or也可以)。因此,如果你重新定义\or基于的宏\ifcase将按预期工作。

好吧,它们会起作用,但只有当测试的整数为 0 时才会起作用,因为在这种情况下 TeX 会扩展重新定义的\or,查找\originalor并跳到匹配的\fi。在“BUMMER”情况下,整个算作 0 情况下的文本(因为其中0\or 1\or 2没有原始值)。\or

\fi这本质上与重新定义或任何其他条件相同。

答案2

只是想指出一些可能很明显的事情(在你的情况下你肯定已经考虑过了),但经常被忽略:如果你的愿望只是你想\or在你的个人.tex文件或公式中输入,并将其视为你已经输入了\lor,那么您可以通过在外部处理输入(具体来说,由你或用户手动输入的部分)来做到这一点,而不是通过 TeX 宏。

(为了简单起见,我们假设您希望在输入文件中的任何地方都\or将其视为输入文件\lor,而不仅仅是在数学模式下。下面的示例显示\or仅在数学模式下重新定义也会导致问题,因此无论如何,特殊处理数学模式不会带来太多好处。)

具体来说,考虑以下输入文件:

\documentclass{article}
\usepackage{amsmath}
\begin{document}

\makeatletter
\let\@oldor\or
\def\or{\ifmmode\lor\else\expandafter\@oldor\fi}
\makeatother

\begin{equation}
(x < 0) \or (x = 0) \or (x > 0)
\end{equation}

\begin{align}
\allowdisplaybreaks[1]
a &= b \\
c &= d
\end{align}
\end{document}

由于内部使用\end{align},它在到达该行时会因难以调试的错误而失败。请参阅以下内容:\allowdisplaybreaks\oramsmath.sty

\interdisplaylinepenalty\@M
\newcommand{\allowdisplaybreaks}[1][4]{%
  \interdisplaylinepenalty\getdsp@pen{#1}\relax
}
\def\getdsp@pen#1{%
  \ifcase #1\@M \or 9999 \or 6999 \or 2999 \or \z@\fi
}

\or我们可以去掉重新定义(上面的部分),而不必在 TeX 中进行重新定义\makeatletter … \makeatother,只需用外部脚本替换每个出现的\orwith\lor即可。(例如,sed 's/\\or\([^a-zA-Z]\)/\\lor\1/g'文件中的内容就可以了。)

使用 LuaTeX(如果我们的设置允许使用它,但在 Mediawiki-texvc 情况下可能不允许),我们可以在文件内部执行此操作:

\documentclass{article}
\usepackage{luacode}
\usepackage{amsmath}
\begin{document}

\begin{luacode*}
luatexbase.add_to_callback('process_input_buffer',
                           function(line)
                              return line:gsub([[\or([^a-zA-Z])]], [[\lor%1]])
                           end,
                           [[Replaces each \or in the input with \lor]])
\end{luacode*}

\begin{equation}
(x < 0) \or (x = 0) \or (x > 0)
\end{equation}

\begin{align}
\allowdisplaybreaks[1]
a &= b \\
c &= d
\end{align}
\end{document}

与早期版本不同,这不会导致使用\or先前定义的宏而出现任何问题。

相关内容