2

So I have been looking into the details of what it means for a macro to be \protected and thus be made robust. I have found this question where an answer explains the concept of what it means for a command to be fragile and what \protect does to fix this, quite well.

However, now I have to wonder: Is there any reason why I would want my command to NOT be robust (aka not use\protect in its definition)? After all, fragile commands seem to cause all kinds of problems and the fix appears to (almost) always be to just add a \protect to the command (or use e.g. \NewDocumentCommand from the xparse package, which afaik does automatically create a protected, aka robust command).

Raven
  • 3,023
  • 1
  • Side note -- nowadays creating robust command uses \protected, not \protect, which is better in a few ways. – user202729 Jul 19 '22 at 08:30
  • 1
    @user202729 No, LaTeX2e \DeclareRobustCommand is unchanged, it still uses \protect. – Joseph Wright Jul 19 '22 at 08:31
  • 1
    Note \NewDocumentCommand does not use the LaTeX \protect mechanism, but the e-tex \protected primitive, which has overlapping use cases with \protect but is fundamentally different – David Carlisle Jul 19 '22 at 08:32
  • Well, then, most of the time it's recommended to create robust commands instead of patching them with \protect (which clutters the source code up), and if you create robust command it's better to use the \protected mechanism than to use the old \protect (which is I think a bit faster and works with raw TeX primitive etc.) – user202729 Jul 19 '22 at 08:50
  • @user202729 except the cases where \protect works but \protected commands do not (notably if the input ends up being used in a \csname, \protect (should be) locally \string so will work, but \protected tokens do not expand so generate low level csname error.) – David Carlisle Jul 19 '22 at 09:21
  • @DavidCarlisle Valid point. But in practice you hardly actually want to construct such a csname anyway...? (or if you insist, maybe for "hashing a token list" (roughly), just detokenize the whole thing?) – user202729 Jul 19 '22 at 09:33

1 Answers1

6

Consider

\documentclass{article}

\newcommand\abc{center}

\newcommand\redef[2]{\def#1{#2}}

\begin{document}

\typeout{here: \abc}

\begin{\abc} xxx \end{\abc}

\redef{\abc}{xyz}

\typeout{here: \abc}

\end{document}

Which produces a log of

here: center
here: xyz

If you add \protect before \abc in the \typeout the log is

here: \abc
here: \abc

If you add \protect in the argument to \redef the log is

! Use of \protect doesn't match its definition.
\end ...after \z@ \expandafter \protect \fi \end

l.20 \end {document} ?

As \protect has been redefined, not \abc

So it depends on the context. \protect prevents expansion, but the current context may be expecting expansion.

\documentclass{article}

\newcommand\abc{center}

\newcommand\redef[2]{\def#1{#2}}

\begin{document}

\typeout{here: \protect\abc}

\begin{\abc} xxx \end{\abc}

\redef{\protect\abc}{xyz}

\typeout{here: \protect\abc}

\end{document}

David Carlisle
  • 757,742