5

Why does \expandafter\newcommand\csname hello\endcsname{Hello world} create a new macro while \expandafter\newcommand{\csname hello\endcsname}{Hello world} creates garbage?

Form what I understand, \csname hello\endcsname programatically creates a new string that can be used as a command name, in this case, something like \hello. You can write both \newcommand\hello{Hello world} and \newcommand{\hello}{Hello world} and they both work. So why is it that when csname is envolved, I have to use the form without curly braces surrounding the name?

2
  • Welcome to TeX.SX! The braces around the macro-to-be-defined name are optional; in your case, you either need an additional \expandafter or to remove the optional braces.
    – egreg
    Commented Jun 28, 2016 at 21:51
  • The \expandafter in the second case doesn't reach the \csname, it expands the brace. Commented Jun 28, 2016 at 21:51

2 Answers 2

4

The “official” syntax for \newcommand is

\newcommand{<macro name>}[<args>]{<text>}

or

\newcommand{<macro name>}[<args>][<default>]{<text>}

but it turns out that the braces around the <macro name> are optional, so long as a single token appears. The braces are good for avoiding mistakes, but some self-control usually suffices.

With

\expandafter\newcommand\csname hello\endcsname{world}

the token \hello is built before \newcommand starts acting and absorbing its first argument (the story is much longer, actually, but this short explanation is precise enough).

On the other hand,

\expandafter\newcommand{\csname hello\endcsname}{world}

will try to expand the brace: \expandafter just acts on a single token, triggering its expansion, if the token is expandable, otherwise doing nothing. You can have the braces, if you prefer, but you need a further \expandafter:

\expandafter\newcommand\expandafter{\csname hello\endcsname}{world}

However this is too much for such a simple construction, isn't it?

If you find yourself in the position of having to do several of these definitions, it's “easy” to build a wrapper

\makeatletter
\newcommand\newnamecommand{\@star@or@long\new@name@command}
\newcommand\new@name@command[1]{\expandafter\new@command\csname #1\endcsname}
\newcommand\renewnamecommand{\@star@or@long\renew@name@command}
\newcommand\renew@name@command[1]{\expandafter\renew@command\csname #1\endcsname}
\newcommand\providenamecommand{\@star@or@long\provide@name@command}
\newcommand\provide@name@command[1]{\expandafter\provide@command\csname #1\endcsname}
\makeatother

\newnamecommand{hello}{Hello World}
\newnamecommand*{helloarg}[1]{Hello #1}

\renewnamecommand{hello}{Whatever}

\providenamecommand{foo}{FOO}
4
  • It's also optional in the last argument, right? \newcommand\foo\baz works, if I remeber correctly.
    – Manuel
    Commented Jun 28, 2016 at 22:06
  • @Manuel Yes, it turns out that such a simple form works, but I wouldn't advertise it.
    – egreg
    Commented Jun 28, 2016 at 22:08
  • You say: "The braces are good for avoiding mistakes". No, in this case the braces only brings mistakes. Like \newcommand{foo} or something similar. So, the "official syntax" for \newcommand is one of many LaTeX bad ideas.
    – wipet
    Commented Jun 29, 2016 at 6:14
  • 1
    @wipet I don't understand; are you on a LaTeXit campaign? Lamport's manual is very consistent with the usage of braces. Instead of letting users ask themselves why braces here and not there, he used braces around every argument. Which is good for beginners, in my opinion; feel free to disagree, but, please, avoid being dogmatic.
    – egreg
    Commented Jun 29, 2016 at 7:15
4

You need to supply an explicit control sequence for \newcommand, and \csname <text>\endcsname is not a control sequence until it is expanded.

Using

\expandafter\newcommand\csname hello\endcsname{<stuff>}

expands to

\newcommand\hello{<stuff>}

as a result of the \expandafter skipping over \newcommand and expanding \csname hello\endcsname to \hello. However,

\expandafter\newcommand{\csname hello\endcsname}{<stuff>}

expands to

\newcommand{\csname hello\endcsname}{<stuff>}

as { is not expandable, making \expandafter useless. If you want to use the "grouped interface for \newcommand", you would need an additional \expandafter:

\expandafter\newcommand\expandafter{\csname hello\endcsname}{<stuff>}

However, without it, \newcommand fails since there's no explicit control sequence.

etoolbox provides a means around this via an interface to \@namedef{<csname>} (from the LaTeX kernel latex.ltx):

\csdef{<csname>}<args>{<stuff>}

That is, you can use

\csdef{hello}<args>{<stuff>}

<args> above are optional but take the \def form of argument specification (or pattern). That is, #1 instead of [1], say.

5
  • \csdef doesn't check whether the token is defined.
    – egreg
    Commented Jun 28, 2016 at 22:04
  • @egreg And doesn't work that way, it's the “cs” version of \def, not of \newcommand.
    – Manuel
    Commented Jun 28, 2016 at 22:05
  • @Manuel Yes, it doesn't accept the number of arguments in brackets.
    – egreg
    Commented Jun 28, 2016 at 22:06
  • @Werner I would say more like \csdef{<csname>}<args>{<stuff>} :)
    – Manuel
    Commented Jun 28, 2016 at 22:10
  • @Manuel: Sure thing. That's also how it's specified in the etoolbox documentation.
    – Werner
    Commented Jun 28, 2016 at 22:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .