将 \newrobustcmd 定义的宏传递给另一个宏会导致一些问题,而 \DeclareRobustCommand 则不会!

将 \newrobustcmd 定义的宏传递给另一个宏会导致一些问题,而 \DeclareRobustCommand 则不会!

我编写了一个宏来对字符串的任何部分进行切片。它可以处理普通字符串,但是当传递给它一个用 \newrobustcmd 定义的字符串时,该宏不起作用并导致错误。(如果使用 \DeclareRobustCommand,则没有问题。)我很困惑为什么会发生这种情况? \DeclareRobustCommand 和 \newrobustcmd 都在创建健壮的命令,但是为什么它们的行为不同?

\documentclass{article}

\usepackage{etoolbox}

\def\slice[#1,#2]#3{
    \newcount\cwords \cwords=1
    \newcount\cstart \cstart=#1
    \advance\cstart by -1\relax
    \def\sentece{}
    \def\empty{}
    \edef\tail{#3\space}
    \def\extract ##1 ##2;{
        \edef\tail{##2}
        \ifnum\cwords>\cstart
            \ifnum\cwords<#2
                \edef\sentece{\sentece\space##1}
            \fi
        \fi            
        \advance\cwords by 1\relax
    }
    \expandafter\extract\tail;
    \loop
        \expandafter\extract\tail;
        \unless\ifx\tail\empty
    \repeat
    \sentece
}

\begin{document}
%    \DeclareRobustCommand\x[1]{This is a test sentece. #1}
%    \DeclareRobustCommand\y{\x{end}}
    \newrobustcmd\x[1]{This is a test sentece. #1}
    \newrobustcmd\y{\x{end}}    
    \slice[3,5]\y
\end{document}

PS 如何才能充分展开一个健壮的宏?

答案1

它们是完全不同的保护形式,

\DeclareRobustCommand\foo{xxx}

定义\foo为,\protect\foox并且它将在中扩展,\edef除非\protect在本地定义(例如,到\noexpand),因此在您的中\edef\tail{#3\space}它会完全扩展。

第二个定义本质上是

\protected\def\foo{xxx}

使用 e-tex\protected原语,这定义了不会扩展的命令并且不使用\edeflatex机制。\protect

请注意,\newcount应该超出您的定义范围,因为您不想在每次使用时分配新的寄存器。此外,所有以}或结尾的行都{应该%避免在输出中生成虚假空格。

相关内容