# Using letter format as parameter for successive macro calls

People!

I want to give the letter format, i.e., \tiny, as parameter for a macro \printarray that calls another macro \subprintarray. With the given code below I expect such a result:

But I get following:

I do not why the letter format is lost in the second macro call. I use the technique of \protected@edef that egreg showed me in a similar question

Here is my code:

\documentclass{letter}
\usepackage{keycommand}
\usepackage{tikz}

\makeatletter
\newkeycommand{\printarray}[myarray={"a","3.4","more", "Test"},arrayformat={\small}, n=3]
{
\edef\tagsaux{\commandkey{myarray}};
\edef\naux{\commandkey{n}};
\protected@edef\formataux{\commandkey{arrayformat}};

\subprintarray[submyarray=\tagsaux, subarrayformat={\formataux}, subn=\naux]
}

\newkeycommand{\subprintarray}[submyarray={"a","3.4","$sin(90)+4$"},subarrayformat={\small}, subn=3]
{
\protected@edef\subtags{\commandkey{submyarray}};

\foreach \xpos in {1,2,...,\commandkey{subn}}{
\path (1.5*\xpos, 1) node { \pgfmathparse{\subtags[\xpos]}\pgfmathresult };
\path (1.5*\xpos, 0) node { \commandkey{subarrayformat} \pgfmathparse{\subtags[\xpos]}\pgfmathresult };
}
}
\makeatother

\begin{document}
\def\tags{{"ABC","b","$\sin(20)+4$","111","4","5","6","7"}}

Call to \texttt{\textbackslash subprintarray}\\
\fbox{
\begin{tikzpicture}
\subprintarray[submyarray=\tags,subarrayformat={\small },subn=4]
\end{tikzpicture}}

Call to \texttt{\textbackslash printarray}\\
\fbox{
\begin{tikzpicture}
\printarray[myarray=\tags,arrayformat={\tiny}, n=4]
\end{tikzpicture}}

\end{document}


I use TikZ-pgf to perform a loop and deal with an array but I don't think that is the problem.

Please do not change the macro calls but modify only inside the macros. (Explanations to better understand the problem/solution are pretty welcome)

Thanks a lot!

• \tiny is a macro that doesn't survive \protected@edef and should be prefixed by \protect in case it eventually ends up in it. – egreg Oct 21 '15 at 21:23
• @egreg : yes it worked writing \protect\tiny as a parameter. Quite practical. Thanks! When I was trying I discovered than \tiny\normalfont also works the desire result, although is inelegant. At the end I found Guho's solution, the \expandafter\noexpand in the macro code, the best compromise between practical and elegant. Thanks for your fast answers. My code looks good and it works! :-) – loved.by.Jesus Oct 23 '15 at 9:26

As far as I can tell, this issue stems from the \tiny option being expanded prematurely in your \protected@edef\formataux{\commandkey{arrayformat}}; line in \printarray. Adding \expandafter\noexpand before \command{arrayformat} to limit the expansion appears to fix it (I end up with your expected result). Adding \noexpand in front of tiny in the call works as well. I'm guessing this is a byproduct of the approach keycommand uses to store the parsed options (\commandkey{arrayformat} expands to \csname keycmd->printarray@arrayformat\endcsname).

I'd recommend using pgfkeys as the behavior is much more intuitive and flexible. Below is your example implemented with pgfkeys - macro calls are unmodified, as requested. In it, the options in \printarray are parsed and the arrayformat is stored directly in \formataux (i.e., \formataux expands to \tiny, as expected):

Edit: Thanks to @cfr for pointing out that the \pgfkeys can be all defined in a single call and that \newcommand{\tags} is a better approach than \def\tags (the former will throw an error if \tags is already defined):

\documentclass{letter}
\usepackage{keycommand}
\usepackage{tikz}
\pgfkeys{/tikz/.cd,%
myarray/.initial={"a","3.4","more", "Test"},
myarray/.get=\tagsaux,
myarray/.store in=\tagsaux,
arrayformat/.initial={\small},
arrayformat/.get=\formataux,
arrayformat/.store in=\formataux,
n/.initial=3,
n/.get=\naux,
n/.store in=\naux,
submyarray/.initial={"a","3.4","$sin(90)+4$"},
submyarray/.get=\subtagsaux,
submyarray/.store in=\subtagsaux,
subarrayformat/.initial={\small},
subarrayformat/.get=\subformataux,
subarrayformat/.store in=\subformataux,
subn/.initial=3,
subn/.get=\subnaux,
subn/.store in=\subnaux}

\makeatletter
\newcommand{\printarray}[1][]{%
\tikzset{#1}
\subprintarray[submyarray=\tagsaux,subarrayformat=\formataux,subn=\naux]
}
\newcommand{\subprintarray}[1][]{%
\tikzset{#1}
\foreach \xpos in {1,2,...,\subnaux}{
\path (1.5*\xpos, 1) node { \pgfmathparse{\subtagsaux[\xpos]}\pgfmathresult };
\path (1.5*\xpos, 0) node { \subformataux \pgfmathparse{\subtagsaux[\xpos]}\pgfmathresult };
}
}
\makeatother

\begin{document}
\newcommand{\tags}{{"ABC","b","$\sin(20)+4$","111","4","5","6","7"}}

Call to \texttt{\textbackslash subprintarray}\\
\fbox{
\begin{tikzpicture}
\subprintarray[submyarray=\tags,subarrayformat={\small },subn=4]
\end{tikzpicture}}

Call to \texttt{\textbackslash printarray}\\
\fbox{
\begin{tikzpicture}
\printarray[myarray=\tags,arrayformat={\tiny }, n=4]
\end{tikzpicture}}

\end{document}


• Very nice example of using arrays in PGF keys (which I find more-or-less incomprehensible in general). Why 2 calls to \pgfkeys, though? Couldn't you set all the keys with a single call? It would be better, if possible, to avoid use of \def in LaTeX since it does no checking to ensure it is not overwriting a command. Especially since \tags seems like just the kind of thing a package might define.... – cfr Oct 21 '15 at 21:14
• @cfr: Indeed you can, thanks for the catch. That was left over from the stepwise adaptation to pgfkeys. Answer updated. – Guho Oct 21 '15 at 21:19
• @cfr: Another great point. I've updated the answer to reflect that. – Guho Oct 21 '15 at 21:24
• @guho, @cfr: you really worked out an elegant answer. At the moment I am using the package keycommand (which is more for dummies ;-)) but, in the future, I am going to use \pgfkeys, it looks great. Thanks a lot! – loved.by.Jesus Oct 23 '15 at 9:34

Some commands don't survive even \protected@edef and among them there are the size changing commands, which are not supposed to be in moving arguments (a moving argument is one that's subject to \protected@edef or \protected@write, usually sectioning commands or captions).

If they are in such moving arguments they must be prefixed by \protect.

Here's a different strategy, that avoids keycommand with its problems and rather uses expl3.

\documentclass{letter}
\usepackage{xparse}
\usepackage{tikz}

\ExplSyntaxOn
\keys_define:nn { lbj/printarray }
{
myarray     .code:n      = \clist_set:No \l_lbj_printarray_myarray_clist { #1 },
arrayformat .tl_set:N    = \l_lbj_printarray_arrayformat_tl,
n           .int_set:N   = \l_lbj_printarray_n_int,
myarray     .initial:n   = {"a","3.4","more", "Test"},
arrayformat .initial:n   = \small,
n           .initial:n   = 3,
}
\keys_define:nn { lbj/subprintarray }
{
submyarray     .code:n      = \clist_set:No \l_lbj_printarray_submyarray_clist { #1 },
subarrayformat .tl_set:N    = \l_lbj_printarray_subarrayformat_tl,
subn           .int_set:N   = \l_lbj_printarray_subn_int,
submyarray     .initial:n   = {"a","3.4","more", "$\sin(90)+4$"},
subarrayformat .initial:n   = \small,
subn           .initial:n   = 3,
}

\NewDocumentCommand{\printarray}{ O{} }
{
\group_begin:
\keys_set:nn { lbj/printarray } { #1 }
\subprintarray[
submyarray=\l_lbj_printarray_myarray_clist,
subarrayformat=\l_lbj_printarray_arrayformat_tl,
subn=\l_lbj_printarray_n_int,
]
\group_end:
}

\NewDocumentCommand{\subprintarray}{ O{} }
{
\keys_set:nn { lbj/subprintarray } { #1 }
\int_step_inline:nnnn {1} {1} {\l_lbj_printarray_subn_int}
{
\path (1.5*##1, 1) node {
\strut
\clist_item:Nn \l_lbj_printarray_submyarray_clist { ##1 }
};
\path (1.5*##1, 0) node {
\l_lbj_printarray_subarrayformat_tl \strut
\clist_item:Nn \l_lbj_printarray_submyarray_clist { ##1 }
};
}
}
\ExplSyntaxOff

\begin{document}

\newcommand\tags{"ABC","b","$\sin(20)+4$","111","4","5","6","7"}

Call to \verb|\subprintarray|\\
\fbox{%
\begin{tikzpicture}
\subprintarray[submyarray=\tags,subarrayformat={\small },subn=4]
\end{tikzpicture}}

Call to \verb|\printarray|\\
\fbox{%
\begin{tikzpicture}
\printarray[myarray=\tags,arrayformat={\tiny}, n=4]
\end{tikzpicture}}

\end{document}


The keys are defined in advance and then set by the command with \keys_set:nn. You can see that it's easy to pass the values from \printarray to \subprintarray. Also extracting an item from a clist variable is easier than with \pgfmathparse.

Instead of \foreach one can use \int_step_inline:nnnn that has no special marker; the current value is simply denoted by #1 (it must be ##1 here because it is inside a definition).