[Tex/LaTex] Command \@ already defined

macros

With the following code,

\documentclass{standalone}
\newcommand{\@s}[1]{\hspace{#1pt}}

\begin{document}
  text
\end{document}

I got the errors:

! LaTeX Error: Command \@ 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.2 \newcommand{\@s}[1]{\hspace{#1pt}}

Your command was ignored.
Type  I <command> <return>  to replace it with another command,
or  <return>  to continue without it.


! LaTeX Error: Missing \begin{document}.

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

l.2 \newcommand{\@s}[1]{\hspace{#1pt}}

You're in trouble here.  Try typing  <return>  to proceed.
If that doesn't work, type  X <return>  to quit.

! Missing number, treated as zero.
<to be read again> 
                   ##
l.2 \newcommand{\@s}[1]{\hspace{#1pt}}

A number should have been here; I inserted `0'.
(If you can't figure out why I needed to see a number,
look up `weird error' in the index to The TeXbook.)

! Illegal unit of measure (pt inserted).
<to be read again> 
                   ##
l.2 \newcommand{\@s}[1]{\hspace{#1pt}}

Dimensions can be in units of em, ex, in, pt, pc,
cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!
I'll assume that you meant to say pt, for printer's points.
To recover gracefully from this error, it's best to
delete the erroneous units; e.g., type `2' to delete
two letters. (See Chapter 27 of The TeXbook.)

! You can't use `macro parameter character #' in horizontal mode.
<recently read> ##

l.2 \newcommand{\@s}[1]{\hspace{#1pt}}

Sorry, but I'm not programmed to handle this case;
I'll just pretend that you didn't ask for it.
If you're in the wrong mode, you might be able to
return to the right one by typing `I}' or `I$' or `I\par'.

What is wrong here? And how should I fix it?

Best Answer

Several things are wrong. @ is a special character in LaTeX. In packages, it has catcode 11, which means it is treated as a letter, but in documents, it is catcode 12, or "other". This means, in the context of your documents, it cannot be part of a multi-character string that makes up the name of a \newcommand, unless you reenable the use of @ as a letter, which you will see in code using \makeatletter, and then discontinued with \makeatother. (Note: catcode "other" symbols can be made as part of a single-character macro name, like \%, \$, or even \@, the source of the current issue)

So, \newcommand{\@s}[1]{\hspace{#1pt}}, because of the status of @ as "other" tries to define the macro \@, not \@s. And \@ is an already defined macro, thus generating an error. You could put a \makeatletter before the \newcommand declaration, but if you reverted back to the normal setting with a \makeatother following the declaration, then an invocation could not be done with \@s (which would be tokenized as \@ and s), but only with \csname @s\endcsname, which is a mouthful.

To use it in a normal document setting, would require something like this

\documentclass{standalone}
\makeatletter
\newcommand{\@s}[1]{\hspace{#1pt}}
\makeatother
\begin{document}
  text\csname @s\endcsname{100}text
\end{document}

enter image description here

It would be easier just to avoid the use of @ altogether in naming your macro, as the intention is to allow package developers to use it only, thus avoiding the potential for conflicts with user-defined macro names.

\documentclass{standalone}
\newcommand{\ats}[1]{\hspace{#1pt}}
\begin{document}
  text\ats{100}text
\end{document}

See? Doesn't that feel better already?