8

I wrote a macro for slicing any part of string. It works with ordinary strings but when a string defined with \newrobustcmd passed to it, the macro doesn't work and causes error. (in case of using \DeclareRobustCommand there is no problem.) I'm so confused why it happens? Both \DeclareRobustCommand and \newrobustcmd are creating robust command, but why they act different?

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

P.S. How can fully expand a robust macro?

11

They are completely different forms of protection,

\DeclareRobustCommand\foo{xxx}

defines \foo to be \protect\foox and this will expand in an \edef unless \protect is locally defined (eg to \noexpand) so in your \edef\tail{#3\space} it fully expands.

The second definition is essentially

\protected\def\foo{xxx}

using the e-tex \protected primitive, this defines commands that do not expand in \edef and the latex \protect mechanism is not used.

Note that \newcount should be outside your definition as you do not want to allocate new registers on each use. Also all the lines ending } or { should have % to avoid generating spurious spaces in the output.

  • Thanks for immediate answer. In second case --using \protected-- how can expand it? – javadr Oct 12 '16 at 0:37
  • @javadr basically, you can't. If you know the protected macro is the first thing you can expand it one step with \expandafter but \protected macros in the body of your string are basically unexpandable. Note also that while your example happens to work in an \edef in general it will not work, most commands that are made robust would give errors in an edef which is why they are made robust (and then in latex you would use \protected@edef which sets up \protect before the \edef – David Carlisle Oct 12 '16 at 0:45
  • Do you mean there isn't anyway to copy the content of \y macro --after expansion-- to another expandable macro?! – javadr Oct 12 '16 at 0:50
  • @javadr you can expand it one step \expandafter\def\expandafter\newy\expandafter{\y} but that (apart from losing \protected) is more or less the same as \let\newy=\y but in general there is no "full expansion". If you attempt to do that with \edef, then commands defined using \protect will typically give errors and commands defined with \protected simply don't expand. – David Carlisle Oct 12 '16 at 0:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.