我写了以下代码:
\newif\ifconsecutive
\consecutivefalse
\newcommand{\myfirst}[1]{#1\consecutivetrue\expandafter\consecutivefalse}
\newcommand{\mysecond}[1]{\ifconsecutive $\longrightarrow$\fi #1}
我的想法是,如果我写
\myfirst{A}\mysecond{B}
我得到的相当于
A $\longrightarrow$ B
而如果我在中间输入一些内容,比如
\myfirst{A} then \mysecond{B}
我得到的却是
A then B
这个想法是,在有效时,\expandafter
会导致调用之后的文本\myfirst
(调用\mysecond
或一些任意其他代码)被扩展,因此如果接下来是调用,则将执行并生成箭头,而如果后面还有其他内容,则不会关心。在扩展之后,应该被调用,导致任何后续的调用\consecutivetrue
\mysecond
\ifconsecutive
\consecutivetrue
\consecutivefalse
\mysecond
都不会生成箭头。
然而什么实际上发生的情况是,无论宏是否连续,箭头都永远不会插入。
现在我的问题是:为什么这对宏不能按预期工作?
以下是完整的可编译代码:
\documentclass{article}
\newif\ifconsecutive
\consecutivefalse
\newcommand{\myfirst}[1]{#1\consecutivetrue\expandafter\consecutivefalse}
\newcommand{\mysecond}[1]{\ifconsecutive $_$\fi #1}
\begin{document}
\myfirst{A}\mysecond{B}
\myfirst{A} then \mysecond{B}
\end{document}
答案1
您不仅想扩展\mysecond
,还想扩展结果,因此您需要在前面\ifconsecutive
加上三个标记。\expandafter
\consecutivefalse
\documentclass{article}
\newif\ifconsecutive
\consecutivefalse
\newcommand{\myfirst}[1]{#1\consecutivetrue\expandafter\expandafter\expandafter\consecutivefalse}
\newcommand{\mysecond}[1]{\ifconsecutive ${}\to\nobreak{}$\fi #1}
\begin{document}
\myfirst{A}\mysecond{B}
\myfirst{A} then \mysecond{B}
\end{document}
但是,我不推荐这种上下文相关的宏。
一个不同的策略是使用,提供的\new@ifnextchar
版本不会吞噬或忽略空格:\@ifnextchar
amsmath
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\newcommand{\myfirst}[1]{#1\new@ifnextchar\mysecond{${}\to\nobreak{}$}{}}
\newcommand{\mysecond}[1]{#1}
\begin{document}
\myfirst{A}\mysecond{B}
\myfirst{A} \mysecond{B}
\myfirst{A} then \mysecond{B}
\myfirst{A}\relax\mysecond{B}
\end{document}
答案2
替代:
\documentclass{article}
\newcommand\mycmd[3][$\longrightarrow$]{#2 #1 #3}
\begin{document}
\mycmd{A}{B}
\mycmd[then]{A}{B}
\end{document}
也可以将命令定义为\mycmd{A}[then]{B}