允许第一个未限定参数为空

允许第一个未限定参数为空

考虑以下宏定义:

\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}

相关内容