1

This question already has an answer here:

I want to make a command that will create a new section or subsection (or subsubsection or...) based on its argument. Why does calling \section and \subsection via \csname not seem to work at all, and how can I fix it? MWE:

\documentclass{article}

\newcommand{\democmd}[2]{%
  \csname #1section \endcsname{#2}%
}

\begin{document}

% Doesn't (visibly, at least) make a subsection.
\democmd{sub}{Should Make a Section}

% Also does not make a section.
\csname section \endcsname{foo}

\end{document}

EDIT: The fixed version is \csname section\endcsname{foo}, no space after section. But why do some macros, like textbf, work as \csname textbf \endcsname{foo} with the space, whereas others, like section and ref, do not?

marked as duplicate by dsedivec, user156344, Mensch, Raaja, Stefan Pinnow Apr 5 at 16:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • The problem is the space before \endcsname. Thanks, LaTeX! Please, whatever you do, don't give me any hints or helpful error messages. Also, I think there is a universal law that I can't find the helpful TeX.stackexchange post until after I have posted my question. – dsedivec Apr 5 at 15:12
  • Have you tried \@nameuse{#1section}{#2} and of course remember \makeatletter/other around the definition because of the @. Though I fail to see where this can be useful. – daleif Apr 5 at 15:12
  • Actually, I added a question about why \csname textbf \endcsname works with the space, which really frustrated me figuring this out. Should this still be a duplicate? I would appreciate input from a more experienced member of the community on this question. – dsedivec Apr 5 at 15:19
  • 2
    Presumably robustness – daleif Apr 5 at 15:29
3

Preliminary note In the sequel, denotes a space in the code, just for clarity.

The fact that sometimes \csname•command•\endcsname works is implementation dependent and should not be relied upon.

Of course the first space is ignored, but the second one isn't, see Absolutely basic \csname question.

Why does it work for \textbf?

This has to do with the protection mechanism for writing to auxiliary files. A command such as \textbf wouldn't survive the basic writing mechanism provided by TeX, so a protection mechanism was devised to avoid it being expanded.

If you do

latexdef \textbf

from the command line you get

\textbf:
macro:->\protect \textbf  

\textbf :
\long macro:#1->\ifmmode \nfss@text {\bfseries #1}\else \hmode@bgroup \text@command {#1}\bfseries \check@icl #1\check@icr \expandafter \egroup \fi 

On the other hand, latexdef -s \textbf will answer

% latex.ltx, line 4054:
\DeclareTextFontCommand{\textbf}{\bfseries}

showing that the definition of \textbf is rather high level.

Basically, \textbf is defined to expand to \protect\textbf• (where the space is part of the name and, guess what, \textbf• is defined by using \csname).

The command \protect can take several values, depending on the context. During normal typesetting its meaning is \relax (do nothing), but during write operations it changes to mean \noexpand (well, not really, but for the purpose of this answer this is not so big a lie).

The result is that during the write operation \textbf is first expanded to \protect\textbf•, which in turn will do \noexpand\textbf• and so the token will be written literally. At the end of the game, the auxiliary file will contain

\textbf••

(one space for the name and one because of how TeX writes out command names). But, when the auxiliary file is read in, TeX will just see \textbf followed by two spaces which will be ignored by rule.

This implementation does what it is thought for, but this fact should not be exploited. Not all commands made robust are treated this way.

Why \section isn't made robust? Because it's very unlikely it will appear in code that needs to be written to an auxiliary file. So \section• is not defined (under standard settings). Thus if you write

\csname•section•\endcsname

TeX will silently replace this with \relax. To the contrary, \section (without a space) is defined, so

\csname•section\endcsname

is equivalent to \section.

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