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?

  • 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 Jun 28 '16 at 21:51
  • The \expandafter in the second case doesn't reach the \csname, it expands the brace. – Ulrike Fischer Jun 28 '16 at 21:51
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}
  • It's also optional in the last argument, right? \newcommand\foo\baz works, if I remeber correctly. – Manuel Jun 28 '16 at 22:06
  • @Manuel Yes, it turns out that such a simple form works, but I wouldn't advertise it. – egreg Jun 28 '16 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 Jun 29 '16 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 Jun 29 '16 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.

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

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.