考虑以下宏定义:
\def\mymacro#1{\mymacroii#1\nil}
\def\mymacroii#1#2\nil{%
\ifx\\#1\\%
empty%
\else
#1%
\fi
}%
\mymacro{foo}% -> f
\mymacro{}
\bye
这应该提取参数的第一个字符\mymacro
。这有效,但前提是参数不为空。
我必须如何更改宏,以便调用\mymacro{}
按预期工作,即输出“空”?请注意,这只是一个简化版本。实际上,我\mymacroii
对第一个字符进行了几次检查,如果它是数字、左括号等等。
这个问题肯定与为什么 TeX 会删除分隔参数周围的括号?,但我无法将这些信息应用到我的案例中。
答案1
\def\mymacro#1{\mymacroii#1{empty}\nil}
\def\mymacroii#1#2\nil{%
#1%
}%
\mymacro{foo}% -> f
\mymacro{}
\bye
在您的版本中,在空的情况下,内部调用是
\mymacroii\nil
#1
就是这样\nil
,然后它开始寻找下一个\nil
(不存在的)来制作#2
,然后事情就出错了。
答案2
请先检查是否为空。
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\mymacro#1{%
\ifx\\#1\\%
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi
{empty}%
{\mymacroii#1\nil}%
}
\def\mymacroii#1#2\nil{#1}
为了体验 LaTeX3 的风格,这里有一个版本,它允许您定义一个函数来检查参数的第一个标记,前提是它首先不为空(在这种情况下它将输出empty
)。它也适用于扩展定义,如下所示。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mymacro}{ m }
{
\tl_if_empty:nTF { #1 }
{ empty }
{ \christoph_examine_first:f { \tl_head:n { #1 } } }
}
\cs_new:Npn \christoph_examine_first:n #1
{
Whatever~you~want~with~#1~which~is~one~token
}
\cs_generate_variant:Nn \christoph_examine_first:n { f }
\ExplSyntaxOff
\begin{document}
\mymacro{foo}
\mymacro{}
\edef\x{\mymacro{foo}\mymacro{}}\x
\end{document}