1

I'm trying this:

\documentclass{article}
\begin{document}
\expandafter\newcommand\csname foo\endcsname{}
\expandafter\newcommand*\csname bar\endcsname{}
\end{document}

The second \newcommand* doesn't work:

! LaTeX Error: Command \csname already defined.
               Or name \end... illegal, see p.192 of the manual.

See the LaTeX manual or LaTeX Companion for explanation. Type H <return> for immediate help. ...

l.4 \expandafter\newcommand*\csname b ar\endcsname{}

I failed to find a hint at this question.

yegor256
  • 12,021

4 Answers4

9

It's worth noting that there are internal LaTeX commands for this purpose:

 \@namedef{NAME}{...}

defines \NAME as a command. These are thin wrappers around the TeX primitive \def, so if you want to have arguments, you need to use the plain syntax, e.g., for a three-argument command:

 \@namedef{NAME}#1#2#3{...}

This would be equivalent¹ to \newcommand*{\NAME}[3]{...} or \NewDocumentCommand{\NAME}{mmm}{...} \newcommand without the * or \NewDocumentCommand specifying +m instead of m would be accomplished using:

 \long\@namedef{NAME}...

Depending on your needs, this might be a more appropriate method.

And to expand on John Kormylo's answer, here's the much simpler² equivalent that uses \NewDocumentCommand instead of \newcommand:

\NewDocumentCommand{\NewNameDocumentCommand}{m}
   {%
     \expandafter\NewDocumentCommand\csname #1\endcsname
   }

  1. Not exactly in that \newcommand checks to see if the command exists with \@ifdefinable before it actually does the definition, while \@namedef doesn't care.

  2. Mostly because \NewDocumentCommand uses a more flexible method of distinguishing between long and short arguments than \newcommand and thus doesn't have a * form. That said, if we wanted to precisely replicate John's definition with \newcommand for the definitions, we could write:³

    \NewDocumentCommand{\Newcommand}{sm}
      {%
        \IfBooleanTF{#1}%
          {\expandafter\newcommand\expandafter*\csname #2\endcsname}%
          {\expandafter\newcommand\csname #2\endcsname}%
      }
    
  3. Comparing the two definitions should make it clear why I'm such a big proponent of \NewDocumentCommand over \newcommand, especially since the former has been part of the LaTeX kernel for almost a year now.

Don Hosek
  • 14,078
4

I also created \Newcommand to apply the \csname automatically. It turns out that \newcommand converts \foo to \\foo internally, so having the name does not save any steps.

\documentclass{article}

\expandafter\newcommand\csname foo\endcsname{test 1} \expandafter\newcommand\expandafter*\csname foobar\endcsname{test 2}

\makeatletter \def\Newcommand{@ifstar@Newcommandstar@Newcommand} \def@Newcommand #1{\expandafter\newcommand\csname #1\endcsname} \def@Newcommandstar #1{\expandafter\newcommand\expandafter*\csname #1\endcsname} \makeatother

\Newcommand{Foo}{test 3} \Newcommand*{Foobar}{test 4}

\begin{document} \foo

\foobar

\Foo

\Foobar \end{document}

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
4

If you avoid LaTeX syntax and use directly TeX syntax, things are more simple:

\def\sdef#1{\expandafter\def\csname#1\endcsname}

\sdef{foo}{test} \long\sdef{Foo}{test2}

\meaning\foo, % normal macro \foo expands to test \meaning\Foo. % long macro \Foo expands to test2

\bye

Of course, you can use \sdef-ed macros with parameters like in \def primitive or you can use \global prefix.

wipet
  • 74,238
4

\newcommand* is two tokens, so you need one more \expandafter to jump over the *, so

\expandafter\newcommand\expandafter*\csname foo\endcsname{<replacement text>}

On the other hand, it's quite pointless to use \newcommand* for a parameterless macro; if you want to check whether a macro defined with \newcommand has empty replacement text, then you can use the \ifdefempty or \ifcsempty tests from etoolbox or define your own version of an empty “long” macro

\newcommand\yegorempty{}

and then macros defined with \newcommand with empty replacement text will be equal to \yegorempty if tested with \ifx.

egreg
  • 1,121,712