5

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?

11

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?

  • \csuse{@s} could be used instead of \ifcsname @s\endcsname (which is slightly easier). – Skillmon Sep 1 '17 at 12:06
  • 1
    @Skillmon Yes, but doesn't that require the etoolbox package? – Steven B. Segletes Sep 1 '17 at 12:09
  • 1
    \newcommand*{\csuse}[1]{\ifcsname #1\endcsname \csname #1\expandafter \endcsname \fi} not that hard (if you don't want the complete etoolbox package). – Skillmon Sep 1 '17 at 12:11
2

You can't create commands which names consist of a mixture of alphabetic chars and special ones. A command name either has exactly one special character, or an arbitrary number of alphabetic ones. Without \makeatletter or outside of a .cls or .sty file, @ is considered a special character, and thus can't be used as an alphabetic character for command names.

The following might work:

\documentclass{standalone}
\makeatletter
\newcommand*{\@s}{foo}
\makeatother

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.