Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Introduction:

When you use \renewcommand within another macro or environment, one needs to double up the ## to access the parameters of the inner macro. This serves as a way to distinguish the inner macros ##1 with the outer macros #1 (even if the outer macro does not have any parameters, it provides for error checking). For example:

\newcommand*{\OuterCommand}{%
    \renewcommand*{\SomeCommand}[1]{\color{red}##1}%
    ....
}%  

The references below provide more details on this.

Issue:

It appears that the same doubling up of the # is needed within a \foreach loop as illustrated in the MWE below.

This took me quite some time to figure this out as the error message that the MWE below gives is:

Illegal parameter number in definition of \pgffor@body

This was within a very deeply nesting of \foreach loops, so I was sure the problem was that I was nesting the \foreach too deeply. Surprisingly, if you skip past the error, the output is still correct, so this made it even harder to locate the problem.

Questions:

  • Since the \foreach does not have parameters like #1 (as \newcommand does), why is it necessary to double up the # within a definition within a \foreach?
  • How is that the output is still correct, if you simply ignore the error and hit return to continue processing?

References:

Code:

\documentclass{article}
\usepackage{xcolor}
\usepackage{pgffor}

\newcommand*{\MyList}{A,B,C}%
\newcommand{\SomeCommand}[1]{#1}%

\begin{document}
\foreach \x in \MyList {%
    \renewcommand*{\SomeCommand}[1]{\color{red}#1}%  Using ## here eliminates the error.
    \par\SomeCommand{\x}%
}%
\end{document}
share|improve this question
2  
Actually you don't need to use ##1 "to access the parameters of the inner macro" it is simply that you need to use ## to enter #. –  David Carlisle Sep 15 '12 at 8:35
    
@DavidCarlisle: Interesting way to look at it. Never thought if # as escaping the #. But, then how do you explain that you need 4 for the next level? :-) –  Peter Grill Sep 15 '12 at 9:20
    
I'll add some notes to the answer, code formatting in comments is rubbish –  David Carlisle Sep 15 '12 at 9:38

1 Answer 1

up vote 17 down vote accepted

Internally the definition of foreach will be saving the body of the loop in a macro so it is like (if looping over a,b,... )

\def\body{%
\renewcommand*{\SomeCommand}[1]{\color{red}#1}%  Using ## here eliminates the error.
    \par\SomeCommand{\x}%
}%
}
\def\x{a}\body
\def\x{b}\body
...

That initial \def (or \newcommand if you prefer) will require a # in the body to be entered as ##. As shown above you would get an error on #1 as \body doesn't take parameters it would have to be entered, as you found, as ##1.

It is possible to define loops in such a way not to require this (for example it could use a token register rather than a macro for saving the body) but that is apparently not the case here.


Note that the need to double # is unrelated to the fact that there is an inner macro definition. It is not that inner macros require ##1 to refer to the first parameter, it is simply that the inner macro definition requires the two tokens # and 1 to refer to the first parameter and to get a # into a macro body you need ##. To see this consider a definition that doesn't have ##1.

You can go

\let\hash=#

and \hash will be let to # but you can not define a macro as

\def\definehash{\let\hash=#}

as that generates

! Illegal parameter number in definition of \definehash.

You need ## to refer to a literal # in a macro definition. So it needs to be

\def\definehash{\let\hash=##}

You ask in comments why it needs four # for a double nested definition. Again it is nothing special about the inner definitions, they never "see" ##1 by the time they are evaluated they just see a single #. If you tried to define

\def\ddefinehash{\def\definehash{\let\hash=##}}

The definition would proceed without error but then if you try to execute \ddefinehash you find that it just has a single # in its definition and so you get the error as before:

! Illegal parameter number in definition of \definehash.
<to be read again> 
                   }
l.12 \ddefinehash

So you need to get two # into the definition of \definehash and each of those has to be entered as ## so you end up with

\def\ddefinehash{\def\definehash{\let\hash=####}}

Putting it all together:

{
\let\hash=#
}

{
\def\definehash{\let\hash=##}
}

{
\def\ddefinehash{\def\definehash{\let\hash=####}}
\ddefinehash
\definehash

\show\ddefinehash
\show\definehash
\show\hash
}

\bye

> \ddefinehash=macro:
->\def \definehash {\let \hash =####}.
l.15 \show\ddefinehash

? 
> \definehash=macro:
->\let \hash =##.
l.16 \show\definehash

? 
> \hash=macro parameter character #.
l.17 \show\hash

? 
 )
No pages of output.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.