Result of "foreach" in extreme cases

From the TikZ documentation (p.902)

Normally, when a list item ... is encountered, there should already have been two list items before it, which where numbers. Examples of numbers are 1, -10, or -0.24. Let us call these numbers x and y and let d := y − x be their difference. Next, there should also be one number following the three dots, let us call this number z.

In this situation, the part of the list reading “x,y,...,z” is replaced by “x, x + d, x + 2d, x + 3d, . . . , x + md,” where the last dots are semantic dots, not syntactic dots. The value m is the largest number such that x + md ≤ z if d is positive or such that x + md ≥ z if d is negative.

I think implicitly m is intended to be a positive integer, and for negative values of z formula is incorrectly described, (as noted in the comments) so in your last three cases, d=2 and m=1 for all cases, which leads to the sequence 2, 2+d= 2,4.

If you want to have a list that just contains (2) you can use:

\foreach \x in {2,...,2} {
   \x
}

I don't think there's a way to end up with a blank list, given the way the list syntax works.

As percusse notes in the comments, the first one or two elements of the list are always executed. To see this, here's a version of your code with a command added to display the value of the increment and the current value at each iteration. (These are lengths defined in pgffor.code.tex).

\documentclass{article}
\usepackage{pgffor}
\usepackage{xcolor}
\makeatletter
\newcommand\dbug{\textcolor{red}{\strip@pt\pgffor@iter;\strip@pt\pgffor@skip}\ }
\makeatother

\begin{document}

\foreach \x in {2,4,...,12} {
   \dbug\x
}

\foreach \x in {2,4,...,4} {
   \dbug\x
}

\foreach \x in {2,4,...,2} {
   \dbug\x
}

\foreach \x in {2,4,...,-1} {
   \dbug\x
}

\end{document}

formatted output of code


Apparently, \foreach \x in {<a>,<b>,...,<c>}{<code>} always executes the cycle with <a> and <b>; then it sees ... and decides what the difference between <a> and <b> is. Only at this point it starts a recursion which terminates when the next number exceeds <c> (in absolute value).

If your values are only integers, you can use expl3 that also has other benefits; for instance, you use #1 instead of \x and you need no trick for expansion; moreover, no group is opened.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
% key-value form
\NewDocumentCommand{\xforeach}{mm}
 {
  \keys_set:nn { pasaba/xforeach }
   {
    start = 0,step = 1,end = 0,#1
   }
  \int_step_inline:nnnn
   { \l_pasaba_xforeach_start_int }
   { \l_pasaba_xforeach_step_int }
   { \l_pasaba_xforeach_end_int }
   { #2 }
 }
\keys_define:nn { pasaba/xforeach }
 {
  start .int_set:N = \l_pasaba_xforeach_start_int,
  step  .int_set:N = \l_pasaba_xforeach_step_int,
  end   .int_set:N = \l_pasaba_xforeach_end_int,
 }
% macro form
\NewDocumentCommand{\sforeach}{mmmm}
 {
  \int_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
 }
\ExplSyntaxOff

\begin{document}

\textbf{Key-value form}

$(2,2,12)$: \xforeach{start = 2,step = 2,end = 12}{#1 }

$(2,2,4)$: \xforeach{start = 2,step = 2,end = 4}{#1 }

$(2,2,2)$: \xforeach{start = 2,step = 2,end = 2}{#1 }

$(2,2,-1)$: \xforeach{start = 2,step = 2,end = -1}{#1 }

\bigskip

\textbf{Command form}

$(2,2,12)$: \sforeach{2}{2}{12}{#1 }

$(2,2,4)$: \sforeach{2}{2}{4}{#1 }

$(2,2,2)$: \sforeach{2}{2}{2}{#1 }

$(2,2,-1)$: \sforeach{2}{2}{-1}{#1 }

\end{document}

enter image description here

Now, suppose you have some \foreach in a macro, say

\newcommand{\foo}[1]{%
  \foreach \x in {2,4,...,#1}{do something with \x}%
}

You can turn it into a macro based on \sforeach with

\newcommand{\foo}[1]{%
  \sforeach{2}{2}{#1}{do something with ##1}%
}

The parameter #1 in \sforeach must become ##1, because it is used inside a macro definition.

Tags:

Foreach