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.

How do you access macro arguments if the macros are nested by more than two levels?

To explain it in more detail: Creating a new command in another command (nesting command definitions), it is possible to implement something like partial application of a command. This is useful for example if a command, which is often called, has two arguments and one changes less frequently than the other:

\documentclass{minimal}
\begin{document}
    \newcommand{\one}[1]{%
        \newcommand{\two}[1]{#1, ##1}%
    }
    \one{a} % Partial application, nothing gets printed
    \two{b} \quad \two{c}
\end{document}

enter image description here

Unfortunately this does not work, if there is another level of nesting involved:

\documentclass{minimal}
\begin{document}
    \newcommand{\one}[1]{%
        \newcommand{\two}[1]{%
            \newcommand{\three}[1]{#1, ##1, ###1}%
        }
    }
    \one{a} % First partial application -> Error
    \two{b} % Second partial application
    \three{c}
\end{document}

The error occurs in the marked line with the following message:

[LaTeX] Line 8: Illegal parameter number in definition of \two.<to be read again>                    a
l.0 \one{c}
         % First partial application -> Error 

As substituting \one{a} by \one{1} in the above code leads to the output 1, b, b, I think that ###1 is interpreted as ##{#1}. So ###1 is expanded to ##a or ##1, respectively. The first one obviously fails, where the second one compiles but leads to an unexpected result. I tested the commands from xparse, too, and the problem seems to be identical.

To rephrase the question above: How do you have ###1 interpreted as {###1} instead of ##{#1} when using the nested command definitions? Why is ##1 in the first example interpreted as {##1} instead of #{#1}?

I know that it is possible to avoid the third level of nesting by some sort of currying as in the following example.

\documentclass{minimal}
\begin{document}
    \newcommand{\one}[1]{%
        \newcommand{\two}[1]{\helper{#1, ##1}}%
    }
    \newcommand{\helper}[1]{%
        \newcommand{\three}[1]{%#1, ##1}%
    }
    \one{1} % First partial application
    \two{b} % Second partial application by currying
    \three{c}
\end{document}

enter image description here

It seems less intuitive and more complicated to me to use two levels of nesting twice instead of three levels of nesting once and I would like to understand how the third level of nesting is used.

share|improve this question
4  
You need four #s in the definition of \three: something like \newcommand{\three}[1]{#1, ##1, ####1}. –  Gonzalo Medina Apr 13 '12 at 18:53
    
Thanks a lot, that works indeed. Can you please add an answer, so that I can vote for it? I am also very interested in an explanation why that works … –  Patrick Häcker Apr 13 '12 at 18:57
    
Related, which also gives a similar explanation as in Gonzalo's answer: What is the meaning of double pound symbol (##1) in an argument? –  Werner Apr 13 '12 at 19:13
    
Thanks, I found a lot of related questions, but I missed this one. –  Patrick Häcker Apr 13 '12 at 19:22

1 Answer 1

up vote 14 down vote accepted

Use four #s in the second nesting level:

\documentclass{article}
\begin{document}
    \newcommand{\one}[1]{%
        \newcommand{\two}[1]{%
            \newcommand{\three}[1]{#1, ##1, ####1}%
        }
    }
    \one{a} 
    \two{b} 
    \three{c}
\end{document}

enter image description here

The following quote from TeX by Topic gives an explanation (further details in section 11.5.5 The macro parameter character):

When TEX’s input processor scans a macro definition text, it inserts a parameter token for any occurrence of a macro parameter character followed by a digit. In effect, a parameter token in the replacement text states ‘insert parameter number such and such here’. Two parameter characters in a row are replaced by a single one.

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.