![\newif 条件导致 \typeout 或 \edef 出现问题](https://linux22.com/image/242893/%5Cnewif%20%E6%9D%A1%E4%BB%B6%E5%AF%BC%E8%87%B4%20%5Ctypeout%20%E6%88%96%20%5Cedef%20%E5%87%BA%E7%8E%B0%E9%97%AE%E9%A2%98.png)
以下代码产生预期的结果,即
假 真
在排版文档上。
\documentclass{minimal}
\newif\iftest
\newcommand{\test}[2]{
\iftest
#1
\else
#2
\fi
}
\newcommand{\ex}{\test{True}{False}\testtrue\test{True}{False}}
\begin{document}
\ex
\end{document}
但是,如果我\ex
用 来包装\typeout
,或者尝试用\edef\ex
来代替,\newcommand
我会得到:
! Incomplete \iffalse; all text was ignored after line...
答案1
这里的问题是\testtrue
不可扩展且不受保护,因此很脆弱。它被定义为\let\iftrue\iftrue
。在可扩展上下文中,例如\edef
或 ,\typeout
赋值\let
被忽略,并且两个 if 开关都被扩展。因为只有一个\fi
(被视为 的一部分\iftrue
),所以编译器会抱怨缺少\fi
。
您可以\test{<true>}{<false>}
在此上下文中使用,但不能使用\testtrue
或\testfalse
。因此,您需要执行以下操作:
\typeset{\test{True}{False}}
\testtrue
\typeset{\test{True}{False}}
我想再给你一个建议。我将\test
宏定义如下:
\makeatletter
\newcommand{\test}{%
\iftest
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother
这样,if 语句在处理两个参数之一之前就已完全处理。这避免了在 if-switch 中使用代码时可能出现的一些问题。例如,使用\newif
和如果要跳过该参数,则在这样的参数内使用它将会中断。\@firstoftwo
和\@secondoftwo
宏只需接受两个参数并扩展为第一个或第二个。 先扩展\expandafter
(即在本例中移除)\else
或\fi
。 还请注意,%
后面的{
是必需的,以避免换行符在那里添加空格。