Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How is it possible to use a declare function in the condition of \foreach? Here's my MWE:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[declare function={a = 0; b = 5;}]
  \foreach \x in {{a},...,{b}}{
    \draw (\x,0) -- (0,\x);
  }
\end{tikzpicture}
\end{document}

This gives me

Missing number, treated as zero.

(line 10, the closing bracket of the loop).

One can even use declared functions in the [options list] of tikzpicture in options coming behind declare function, but why not simply in \foreach?

share|improve this question
    
I guess you can’t use it in foreach, because it doesn’t evaluate math at all, sin(2) doesn’t work either, does it? –  Tobi Apr 26 '13 at 20:43
1  
As already pointed out by comments and answers, you need to evaluate the values first. Although it is possible to say to evaluate an expression inside the loop using \foreach \x[evaluate=\x] in {…} the loop still uses the un-evaluated values, in this case the loop goes still from a to b and not from 0 to 5. {a, ..., e} would loop over a, b, c, d and e which could be some constants that get evaluated. You can't use it to loop over their values, unfortunately. –  Qrrbrbirlbel Apr 26 '13 at 20:56

2 Answers 2

up vote 5 down vote accepted

You can evaluate the expression first:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[declare function={a=0;b = 5;}]
\pgfmathparse{{a}}\let\pgfmathresulta\pgfmathresult
\pgfmathparse{{b}}\let\pgfmathresultb\pgfmathresult
  \foreach \x in {\pgfmathresulta,...,\pgfmathresultb}{
    \draw (\x,0) -- (0,\x);
  }
\end{tikzpicture}

\end{document}
share|improve this answer
    
Ah, my question was not detailed enough. I edited it. I actually need two functions in the range. But \pgfmathresult is only one container. –  Foo Bar Apr 26 '13 at 20:39
    
In this case you could use \pgfmathsetmacro{<macro>}{<math expression>} and then use <macro> –  Tobi Apr 26 '13 at 20:41
    
@Tobi Thanks, this works. :) –  Foo Bar Apr 26 '13 at 20:44
    
@FooBar you could just use two macros one for each. I'll update to match –  David Carlisle Apr 26 '13 at 20:44
    
@DavidCarlisle Thanks, I will then accept your answer. :) –  Foo Bar Apr 26 '13 at 20:45

This small code adds two keys to the optional \foreach use:

  • use int and
  • use float

I let the example speak for themselves:

\begin{tikzpicture}[declare function={a = 0; b = 5;}]
  \foreach \x[use int=a to b] \draw (\x,0) -- (0,\x);
\end{tikzpicture}

\begin{tikzpicture}
    \foreach \x[use int=2 to 10 step 2] {
        \ifnum\x=\foreachEnd
            \tikzset{every path/.append style=thick}
        \fi
        \draw (\x/2,0) -- (0,\x/3);
    }
\end{tikzpicture}

Disclaimer: No warranties; probably breaks the very next moment.

Code

\documentclass[tikz]{standalone}
\usepackage{tikz}
\makeatletter
\newif\ifqrr@pgf@foreach@no@list
\pgfkeys{
    /pgf/foreach/.cd,
    @use/.code args={#1to#2}{%
        \qrr@pgf@foreach@no@listtrue
        \qrr@pgf@foreach@no@list@use\foreachStart{#1}%
        \pgfutil@in@{step}{#2}
        \ifpgfutil@in@
            \qrr@pgf@foreach@no@list@parse@step#2\pgffor@stop
        \else
            \qrr@pgf@foreach@no@list@parse@step#2step1\pgffor@stop
        \fi
        \edef\qrr@pgf@foreach@no@list@list{\foreachStart,\foreachSecond,...,\foreachEnd}},
    use int/.code={%
        \let\qrr@pgf@foreach@no@list@use\pgfmathtruncatemacro
        \pgfkeysalso{/pgf/foreach/@use={#1}}%
    },
    use float/.code={%
        \let\qrr@pgf@foreach@no@list@use\pgfmathsetmacro
        \pgfkeysalso{/pgf/foreach/@use={#1}}%
    }
}
\def\qrr@pgf@foreach@no@list@parse@step#1step#2\pgffor@stop{%
    \qrr@pgf@foreach@no@list@use\foreachEnd{#1}%
    \qrr@pgf@foreach@no@list@use\foreachSecond{\foreachStart+#2}%
}
\def\pgffor@vars{% manually extended, better etoolbox
    \pgfutil@ifnextchar i{\pgffor@@vars@end}{%
        \pgfutil@ifnextchar[{\pgffor@@vars@opt}{%]
            \pgfutil@ifnextchar/{\pgffor@@vars@slash@gobble}{%
                \ifqrr@pgf@foreach@no@list\expandafter\pgfutil@firstoftwo\else
                    \expandafter\pgfutil@secondoftwo\fi
                {\qrr@pgf@foreach@no@listfalse\pgffor@macro@list\qrr@pgf@foreach@no@list@list}
                {\pgffor@@vars}}}}}%
\makeatother
\begin{document}
\begin{tikzpicture}[declare function={a = 0; b = 5;}]
  \foreach \x[use int=a to b] \draw (\x,0) -- (0,\x);
\end{tikzpicture}

\begin{tikzpicture}
    \foreach \x[use int=2 to 10 step 2] {
        \ifnum\x=\foreachEnd
            \tikzset{every path/.append style=thick}
        \fi
        \draw (\x/2,0) -- (0,\x/3);
    }
\end{tikzpicture}
\end{document}

Output

enter image description here

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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