我尝试了以下三种方法aaa
为名称取决于条件的宏赋予值(这里是)。
只有第三个有效。但是,该值aaa
必须写入两次。如果该值很长,这会很烦人。
还有更好的办法吗?
代码:
\documentclass[a4paper]{article}
\usepackage{}
\usepackage{geometry}
\geometry{showframe}
\geometry{left=1cm,right=1cm,top=1cm,bottom=1cm}
\parindent0pt
\begin{document}
Method 1:
% \expandafter\def\ifnum 5>4 \aaa\else\bbb\fi{aaa}
% \aaa
Method 2:
% \ifnum 5>4\def\aaa\else\def\bbb\fi{aaa}
% \aaa
Method 3:
\ifnum 5>4\def\aaa{aaa}\else\def\bbb{aaa}\fi
\aaa
\end{document}
答案1
TeXbook,第 20 章:定义(也称为宏)说:
- 条件。当
\if...
被展开时,TeX 会尽可能地向前读取以确定条件是真还是假;如果为假,它会向前跳过(跟踪\if...\fi
嵌套),直到找到\else
、\or
或\fi
来结束跳过的文本。同样,当\else
、\or
或\fi
被展开时,TeX 会读取到任何应该跳过的文本的末尾。条件的“展开”为空。(条件总是减少消化过程后期阶段看到的标记数量,而宏通常会增加标记数量。)
% Here toplevel-expansion of \ifnum ends before the 1st token of the true-branch/\if..-branch.
% \expandafter..\expandafter in the true-branch/\if..-branch is used to make the entire \else..\fi-branch go away:
\ifnum 5>4 \expandafter\def\expandafter\aaa\else
\expandafter\def\expandafter\bbb\fi{aaa}%
\expandafter\show\ifnum 5>4 \aaa\else\bbb\fi
% Here toplevel-expansion of \ifnum ends before the 1st token of the false-branch/\else..-branch.
% \expandafter..\expandafter in the false-branch/\else..-branch is used to make the token `\fi` go away:
\ifnum 5>5 \expandafter\def\expandafter\aaa\else
\expandafter\def\expandafter\bbb\fi{aaa}%
\expandafter\show\ifnum 5>5 \aaa\else\bbb\fi
\csname bye\endcsname
\stop
虽然这个答案的目的是展示带有 \if..\else..\fi
表达式的扩展步骤,这更表明了一个教学目标,但擦拭和埃格尔在我看来,最好地展示如何在实践中实际处理事情。
答案2
有条件地做\newcommand
。
\documentclass{article}
\makeatletter
\newcommand{\conditionalnewcommand}[3]{%
% #1 = test, #2 = name for true, #3 = name for false
#1\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\newcommand#2}{\newcommand#3}%
}
\makeatother
\conditionalnewcommand{\ifnum5>4}{\aaa}{\bbb}{this is aaa}
\conditionalnewcommand{\ifnum3>4}{\aaa}{\bbb}{this is bbb}
\begin{document}
\aaa
\bbb
\end{document}
另一方面,如果这是包代码,并且命令名称依赖于某些开关,例如\ifpackage@foo
,您可以执行
\newcommand\package@command{whatever}
\@onlypreamble\package@command
\ifpackage@foo
\@ifdefinable{\aaa}{\let\aaa\package@command}
\else
\@ifdefinable{\bbb}{\let\bbb\package@command}
\fi
答案3
我会在其中使用\csname ...\endcsname
配对和条件:\if
\expandafter \def \csname \ifnum 4>5 aaa\else bbb\fi \endcsname {...}
您的实验很糟糕,因为\if
条件评估了条件但没有关闭整个构造,即\else
在启动\fi
时保持不变。\def