6

Hi so have some list of data which I've define as macros. Everything below are all in a package.

\newcommand{\testa}[0]{1/2/2/1,3/4/2/3}

I have many more of these predefined. I also have a command which I would like to utilize these macros I've defined earlier.

\newcommand{\dosomething}[1]{
\begin{tikzpicture}
\foreach \x / \y / \a / \b in {#1} {
\draw[black,line width=0.1cm] (\a,\b) -- (\x,\y);
};
\end{tikzpicture}
}

But here is the problem. This is whats happening when I try to use them outside of the package.

% The following works
\dosomething{1/2/2/1,3/4/2/3}
% This however does not...
\dosomething{\testa}

I end up getting the error

! Missing = inserted for \ifnum
<to be read again>
                   /

There is clearly something that I am misunderstanding but I'm not sure what. I've tried searching for this problem but I couldn't find something to what I was looking for or I might have just too little understanding of latex to correlate it to my own problem. Thanks for the help.

1 Answers1

6

Since you're going to use coordinates, you can expand the argument:

\newcommand{\dosomething}[1]{%
  \edef\dosomethingargument{#1}%
  \begin{tikzpicture}
    \foreach \x / \y / \a / \b in \dosomethingargument {
      \draw[black,line width=0.1cm] (\a,\b) -- (\x,\y);
    };
  \end{tikzpicture}%
}

Full example

\documentclass{article}
\usepackage{tikz}

\newcommand{\dosomething}[1]{%
  \edef\dosomethingargument{#1}%
  \begin{tikzpicture}
    \foreach \x / \y / \a / \b in \dosomethingargument {
      \draw[black,line width=0.1cm] (\a,\b) -- (\x,\y);
    };
  \end{tikzpicture}%
}

\newcommand{\testa}{1/2/2/1,3/4/2/3}

\begin{document}

\section{Explicit}

\dosomething{1/2/2/1,3/4/2/3}

\section{Implicit}

\dosomething{\testa}

\end{document}

enter image description here

In case \testa can contain something dangerous for \edef, use

\edef\dosomethingargument{\unexpanded\expandafter{#1}}

What’s the trick? The macro \foreach expects the set of variables, followed by in; then it checks for a brace. If it finds it, \foreach interprets the text up to the matching closed brace as the set of items for the loop. Otherwise, the token after in should be a macro, which \foreach takes as the container of the items for the loop.

Thus with \foreach \x/\y/\a/\b in {\testa} the loop is performed over a single item. Conversely, \foreach \x/\y/\a/\b in \testa will perform the loop on all the items contained in \testa. By doing \edef we can always pass \foreach a macro.

egreg
  • 1,121,712
  • Thanks! This really helped a lot :) . I was wondering if you could explain to me why I need to define it? I guess I just want to understand why latex was complaining to begin with and why \edef fixes that here. – Amlesh Sivanantham Jan 19 '18 at 02:21