# \rule doesn't work inside an \xdef command

This code:

 \documentclass{article}
\begin{document}
\def\a{}
\newcounter{mycounter}
\def\b#1{
\def\p{#1}
\ifnum\value{mycounter}=0
\long\xdef\a{\a\rule{3mm}{3mm}\par #1}
\else
\long\xdef\a{\a #1\ }
\fi
}
\b{A}\b{B}\b{C}\b{D}\b{E}\b{F}
\setcounter{mycounter}{1}
\b{G}\b{H}\b{I}\b{J}\b{K}
\a
\end{document}


throws the ERROR:

 "!Paragraph ended before \@newctr was complete.<to be read again>\par b{A}"


What's happening?

-

It can't work like that: \rule does assignments that are not performed in an \xdef.

You probably want to say

\expandafter\gdef\expandafter\a\expandafter{\a\rule{3mm}{3mm}\par #1\ }


and similarly for the other line. The \long is useless, since \a has no arguments.

It seems that you want to add something to the expansion of \a, but \xdef does "expansion all the way", while you need to get only at the first level expansion of \a. The sequence of \expandafter's will do just it. However there's a more efficient way to define your macro:

\makeatletter
\def\b#1{%
\def\p{#1}%
\ifnum\value{mycounter}=0
\else

The macro \g@addto@macro is in the LaTeX kernel and its effect is exactly to append (globally) the second argument to the replacement text of the first argument, which should be a macro.
@Philipp: well, no; \xdef wants to expand all the way and it will find a previously added \rule; \noexpand acts only once and when the token after it is put into a replacement text it will be expanded when needed. –  egreg Jul 4 '11 at 20:13
Then \xdef\a{\unexpanded\expandafter{\a\rule...#1}}. Also, you need to double # in your first example. –  Bruno Le Floch Jul 4 '11 at 20:59
@Bruno: where is it necessary to double the #? –  egreg Jul 4 '11 at 21:08
\expandafter\gdef\expandafter\a\expandafter{\a\rule{3mm}{3mm}\par #1\ } produces the error ! Illegal parameter number in definition of \a. EDIT: I didn't realize that it was within some other command, sorry. –  Bruno Le Floch Jul 4 '11 at 22:19