# Nested styles in TikZ

I have:

\pgfkeys{/TransformerNetwork/.style={
transformer/.style 2 args={draw, cylinder, gray!80, rotate=90, minimum height=#1, minimum width=#2},
}}


And then:

\begin{tikzpicture}[/TransformerNetwork]
\node [transformer={2.3cm}{1cm}] () at (0,0.6) {};


but tikz complains:

Illegal parameter number in definition of \pgfkeys@temp.


How do I let it know that the 2 arguments are for the nested style?

I agree with Jake that there's no need here to nest the definitions of the styles, but just in case a more complicated situation comes along where you do need to nest them (or at least, not being able to do so becomes a really hassle), the solution to the problem is simple and is essentially the same problem as nesting definitions.

That is to say, if you put the following code in a document

\def\a{\def\b#1{got #1}}


you will get exactly the same error message:

! Illegal parameter number in definition of \a.


So what's happening here is that something is getting \defed behind the scenes and the contents of the style is getting transformed in to the body of that \def. This means that the #1 and #2 are interpreted as the arguments of the outer style. The way to get them to work as you expect is to double the hashes. That is to say,

\def\a{\def\b##1{got ##1}}


works: when \a is executed it is replaced in the stream by \def\b#1{got #1}.

Translated back in to your style, this becomes:

\pgfkeys{/TransformerNetwork/.style={
transformer/.style 2 args={draw, rectangle, gray!80, rotate=90, minimum height=##1, minimum width=##2},
}}


and now it works as you want it to.

It's good that you tried this with a style with 2 arguments as you wouldn't have gotten an error with one argument since styles can by default take an argument. That is,

\pgfkeys{/TransformerNetwork/.style={
transformer/.style 2 args={draw, rectangle, gray!80, rotate=90, minimum size=#1},
}}


does not produce an error, but the value substituted in at #1 needs to be provided by the TransformerNetwork style and not the transformer style. Any argument provided to the transformer style would be thrown away.

It is, of course, possible to pic 'n' mix this syntax, and to good effect.

\documentclass{standalone}
% \url{http://tex.stackexchange.com/q/21414/86}
\usepackage{tikz}

\pgfkeys{/TransformerNetwork/.style 2 args={
transformer/.style 2 args={draw=#1, rectangle, rotate=#2, minimum height=##1, minimum width=##2},
}}

\begin{document}
\begin{tikzpicture}
\begin{scope}[/TransformerNetwork={red}{50}]
\node [transformer={2.3cm}{1cm}] () at (0,0.6) {};
\node [transformer={2cm}{1.5cm}] () at (3,0.6) {};
\end{scope}
\begin{scope}[/TransformerNetwork={green}{80},yshift=-3cm]
\node [transformer={2.3cm}{1cm}] () at (0,0.6) {};
\node [transformer={2cm}{1.5cm}] () at (3,0.6) {};
\end{scope}
\end{tikzpicture}
\end{document}


Produces:

• Amazing! Thanks, this is exactly what I wanted. My example is actually more complicated. I had pruned it down to make it easier on answerers. Jun 23 '11 at 7:43
• Note that at each level, the number of # is doubled, so at level 3 you need ####1. Oct 12 at 14:28

You shouldn't nest the definitions of the styles. Define the inner one (transformer) and then call that in the definition of the outer style (TransformerNetwork). Also, TransformerNetwork should be a .style 2 args so it can handle the two parameters that are then passed on to the inner style:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes}
\begin{document}

\pgfkeys{
/tikz/transformer/.style 2 args={
draw,
cylinder, gray!80,
rotate=90,
minimum height=#1,
minimum width=#2
},
/TransformerNetwork/.style 2 args={
transformer={#1}{#2},
}
}

\begin{tikzpicture}
\node [/TransformerNetwork={2.3cm}{1cm}] () at (0,0.6) {};
\end{tikzpicture}
\end{document}

• Thanks for your answer. I clarified in my question what I was trying to do, but in fact, I can just do what you suggest since all of my "transformer"s are the same size. Jun 23 '11 at 6:20