3

I would like to pass an array as the first argument to a pic. However, the naive method doesn't work:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\tikzset{
    ball/.pic = {
        \draw [fill=red] (0,0) circle [radius=4mm];
    },
    balls/.pic = {
        \foreach \pos in #1 {
            \pic at (\pos,0) {ball};
        }
    }
}

\begin{document}

\begin{tikzpicture}
    \draw (0,0) pic {balls={3,5}};
\end{tikzpicture}

\end{document}

I also tried with the syntax that should be used "for more complex arguments":

pics/balls/.style = {
        code = {
            \foreach \pos in #1 {
                \pic at (\pos,0) {ball};
            }
        }
    }

but this still does not work.

I know how to pass multiple arguments to a pic with /.style n args, however this is not what I'm trying to do.

How can this be achieved?

glS
  • 546
  • 1
    Add braces around #1 so it becomes {#1} in the first code – percusse Dec 16 '15 at 10:14
  • @percusse I realized that was the solution just 5 seconds ago, sorry. Should I delete the post or do you think showing the correct syntax could be useful to others? – glS Dec 16 '15 at 10:15
  • You can answer your own question after some time I guess. No need to delete anything. – percusse Dec 16 '15 at 10:17
  • @percusse I'll do that. Anyway it would be nice to understand why is that the correct syntax. I did not try it at first because I though the array, with braces, would have been directly passed into the foreach – glS Dec 16 '15 at 10:19
  • 1
    There is a nontrivial answer to that but shortly. The arguments of pgfkeys are stripped off braces at each level of nesting once. It is a pretty involved thing to keep track of so best is to protect where it is needed. Sometimes you have to do the other way around where you have to explicitly strip off braces such that it doesn'r see it as single element etc. – percusse Dec 16 '15 at 10:23
  • @percusse could you show the syntax to do that, i.e. to "protect"? – glS Dec 16 '15 at 10:25
  • Braces around #1 in your case is an example. The other way is, say, http://tex.stackexchange.com/questions/261607/can-foreach-handle-list-of-lists and many others around the site – percusse Dec 16 '15 at 10:27
  • 1
    @glS I am eternally grateful that you did not delete this! – Utkan Gezer Jun 28 '20 at 15:24

1 Answers1

3

The solution was very simple: just enclose the #1 argument into curl braces. Applying such correction the code works as expected:

\documentclass[border=10pt]{standalone}
\usepackage{tikz}

\tikzset{
    ball/.pic = {
        \draw [fill=red] (0,0) circle [radius=4mm];
    },
    balls/.pic = {
        \foreach \pos in {#1} {
            \pic at (\pos,0) {ball};
        }
    }
}

\begin{document}

\begin{tikzpicture}
    \draw (0,0) pic {balls={0,3,5,7,9}};
\end{tikzpicture}

\end{document}

produces

enter image description here

The reason why this is needed has been briefly explained in a comment to the original post by percusse, which I quote here:

There is a nontrivial answer to that but shortly. The arguments of pgfkeys are stripped off braces at each level of nesting once. It is a pretty involved thing to keep track of so best is to protect where it is needed. Sometimes you have to do the other way around where you have to explicitly strip off braces such that it doesn'r see it as single element etc.

glS
  • 546