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.

The following example from page 508 of PGF manual 2.40 gives me a result that I didn't expect.

\tikz[x=0.75cm,y=0.75cm]
  \foreach \x [count=\xi] in {a,...,e}
  \foreach \y [count=\yi] in {\x,...,e}
  \node [draw, top color=white, bottom color=blue!50, minimum size=0.666cm]
    at (\xi,-\yi) {$\mathstrut\x\y$};

enter image description here

I expected to see bc, bd, be, cd, ce, de.

The following gives the expected output:

\tikz[x=0.75cm,y=0.75cm]
  \foreach \x [count=\xi] in {1,...,5}
  \foreach \y [count=\yi] in {\x,...,5}
  \node [draw, top color=white, bottom color=blue!50, minimum size=0.666cm]
    at (\xi,-\yi) {$\mathstrut\x\y$};

enter image description here

I guess there is a bug in \foreach.

My own \newforeach gives

enter image description here

using the code

\tikz[x=0.75cm,y=0.75cm]
  \newforeach [count=\xi] \x in {a,...,e}
  \newforeach [count=\yi,expand before fill] \y in {\x,...,e}
  \node [draw, top color=white, bottom color=blue!50, minimum size=0.666cm]
    at (\xi,-\yi) {$\mathstrut\x\y$};

This last output was what I expected from \foreach. Unfortunately, \newforeach isn't yet released because it is still being tested. You can ask for it and participate in testing it.

share|improve this question
    
Interesting. The only way I can get the behavior I expect is to use {a,b,c,d,e} instead of {a,...,e}. If you use {a,b,...,e} then the first two columns are correct, but not the third and fourth.. –  Peter Grill Sep 16 '12 at 4:14

1 Answer 1

up vote 10 down vote accepted

If you try

\foreach \x [count=\xi] in {1,...,5}
\foreach \y [count=\yi] in {\x,...,5}

then all is well: the problem is a bug in how the \foreach code handles alphabetic iteration. The relevant code is

\def\pgffor@makealphabetic#1{%
    % Convert the number in the macro passed as #1 to a-z or A-Z.
    \pgfutil@tempcnta=#1\relax%
    \ifnum\pgfutil@tempcnta>95\relax%
        \advance\pgfutil@tempcnta by-96%
        \expandafter\def\expandafter#1\expandafter%
            {\pgffor@alpha\pgfutil@tempcnta}%           
    \else%
        \advance\pgfutil@tempcnta by-64%
        \expandafter\def\expandafter#1\expandafter%
            {\pgffor@Alpha\pgfutil@tempcnta}%                           
    \fi%
}

Here, #1 is the temporary variable used to hold what will be printed/used as \x, \y, etc. It's a number, but is converted by the code above to a letter. However, the above does not do this correctly: all those \expandafters do not expand \pgfutil@tempcnta, which is what is actually needed. For me

\def\pgffor@makealphabetic#1{%
    % Convert the number in the macro passed as #1 to a-z or A-Z.
    \pgfutil@tempcnta=#1\relax%
    \ifnum\pgfutil@tempcnta>95\relax%
        \advance\pgfutil@tempcnta by-96\relax%
        \edef#1{\pgffor@alpha\pgfutil@tempcnta}%        
    \else%
        \advance\pgfutil@tempcnta by-64\relax%
        \edef#1{\pgffor@Alpha\pgfutil@tempcnta}%                            
    \fi%
}

fixes the issue as the letters are now 'baked in'.

(I've not traced it all through, but my guess is that with an explicit iteration list, there is no numerical part involved, hence you only see this when using ... notation.)


It's quite instructive to disable the conversion entirely here:

\documentclass{article}
\usepackage{tikz}
\makeatletter
\def\pgffor@makealphabetic#1{}
\makeatother
\begin{document}
\tikz[x=0.75cm,y=0.75cm]
  \foreach \x [count=\xi] in {a,...,e}
  \foreach \y [count=\yi] in {\x,...,e}
  \node [draw, top color=white, bottom color=blue!50, minimum size=0.666cm]
    at (\xi,-\yi) {$\mathstrut\x\y$};
\end{document}

as this shows up that \foreach deals with first case separately from all of the others. I'm not sure that's a great plan, as it leaves open the danger of variable behaviour.

share|improve this answer
    
Reported as sourceforge.net/tracker/… –  Joseph Wright Sep 16 '12 at 8:17
    
@AhmedMusa Not needed here as the \edef is non-expandable, so TeX will do the assignment as expected: exactly the same as in the original definition. I do agree though it's 'better style' to terminate the assignment properly, either with \relax or a space. –  Joseph Wright Sep 16 '12 at 12:55
    
I think there should be \relax after -96 and -64, as \advance tries to expand \edef. I have added it. But your patch doesn't solve the problem. Did you actually try it? –  Ahmed Musa Sep 16 '12 at 13:07
    
@AhmedMusa I've just double-checked: yes, the change I have does work for me with your example. The change needs to be made after loading TikZ, of course, but other than that there is nothing special going on. –  Joseph Wright Sep 16 '12 at 13:13
    
I am sorry, it works. I added the patch with with @ having catcode 12. –  Ahmed Musa Sep 16 '12 at 13:20

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.