4

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
    Welcome to TeX.SX! You need to expand the argument before using it in the way you do. – TeXnician Jan 18 '18 at 19:22
  • 1
    Try \expandafter\dosomething\expandafter{\testa} (untested, however), as a possible way what @TeXnician mentioned.... – user31729 Jan 18 '18 at 19:23
  • Alright, I tested it out and im getting a new error "Missing Number, treated as zero" – Amlesh Sivanantham Jan 18 '18 at 20:43
5

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.

  • 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 2:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.