14

An example is a bit artificial, but the point is that I do not understand why {} influence the outcome of \newcommand in the way described below.

Consider the following definition:

\newcommand\printit[1]{#1}

whose outcome is obvious. However, a small alteration:

\newcommand{\printit[1]}{#1}

and e.g. \printit{2} yields:

enter image description here

I have no idea why. Could you please shed some light on what is going on here?

  • 1
    \def\new@command#1{% \@testopt{\@newcommand#1}0} from latex.ltx, i.e. LaTeX tests whether there is an optional argument in the first argument of \newcommand, i.e. \printit[1] and returns 0, the {2} in its usage is not regarded as an argument. You could use \printit without {} and it will still print 0, use it as \printit[2] and it will print 2. In fact you have defined a macro with optional arguments in a non-obvious way – user31729 Jan 13 at 20:00
  • The correct syntax is \newcommand\printit[1]{#1} or \newcommand{\printit}[1]{#1} (The number of parameters to be expected is given in square brackets, outside of the {}). In case people come across this and are confused by the above syntax. – Peter Grill Jan 13 at 20:07
  • @PeterGrill Yes, I know the correct syntax. But I was curious why grouping \printit[1] results in the (rather unexpected) outcome. – Mad Hatter Jan 13 at 22:09
  • @MadHatter: Yep, I figured that. My comment was intended for others who may come across this and be confused. – Peter Grill Jan 13 at 22:46
21

If LaTeX was being written now,

\newcommand{\printit[1]}{#1}

would give an error message that \printit[1] was not a single token.

The correct syntax is

\newcommand{\printit}[1]{#1}

or

\newcommand\printit[1]{#1}

LaTeX does nothing special to allow both forms, it is just on the general TeX macro syntax rules that braces can be omitted if a macro argument is a single token.

If you pass two (or in this case, four) tokens to \newcommand then anything that happens is essentially just accidental behaviour, as the system could not really afford the space or time required to catch "unlikely" errors.

As to what happens,

\documentclass{article}

\begin{document}

\newcommand{\printit[1]}{#1}

\show\printit
\expandafter\show\csname\string\printit\endcsname
\end{document}

produces the terminal log

> \printit=macro:
->\@protected@testopt \printit \\printit {0}.
l.7 \show\printit

? 
> \\printit=\long macro:
[#1]->#1.

The command defines \printit to have an optional first argument, although the default value of 0 being supplied was intended as the default value for \newcommand itself. it is what makes \newcommand\foo the same as \newcommand\foo[0] and define a command with no arguments.

The inner part of the command handling the optional argument is \\printit which just drops the square brackets.

So

 \printit{2}

is

 \printit[0]{2}

which is

0{2}

which typesets as 02

  • What about LaTeX3, which is being written now? ;-) – Socob Jan 14 at 1:58
  • 3
    @Socob I hadn't actually checked but add \usepackage{xparse} and replace \newcommand by \NewDocumentCommand and you get ! LaTeX3 Error: First argument of '\NewDocumentCommand' must be a command. – David Carlisle Jan 14 at 7:55

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.