极端情况下的“foreach”结果

极端情况下的“foreach”结果

在以下测试中:

\documentclass[spanish,10pt]{beamer}
\usepackage{pgfplots}

\begin{document}

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

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

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

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

\end{document}

结果是以下四行:

2 4 6 8 10 12
2 4
2 4
2 4

前两行符合预期,但最后两行不符合:我预期“2”和空行(在其他编程语言中很常见)。

有什么提示可以获得这些结果吗?(在真实来源中,最终数字是一个未知参数)。

答案1

显然,总是用和\foreach \x in {<a>,<b>,...,<c>}{<code>}执行循环;然后它查看并确定和之间的差值。只有在此时,它才会启动递归,当下一个数字超过(绝对值)时,递归才会终止。<a><b>...<a><b><c>

如果您的值只是整数,那么使用expl3它也有其他好处;例如,您使用#1而不是\x并且您不需要扩展技巧;此外,没有打开任何组。

\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}

在此处输入图片描述

现在假设你\foreach在一个宏里有一些,比如

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

\sforeach您可以将其转换为基于的宏

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

#1中的参数\sforeach必须变成##1,因为它在宏定义内部使用。

答案2

摘自 TikZ 文档 (p.902)

通常,当遇到列表项 ... 时,它之前应该已经有两个列表项,其中是数字。数字的示例有 1、-10 或 -0.24。我们称这些为数字X然后让d := y − x是它们的差值。接下来,三个点后面还应该有一个数字,我们把这个数字称为

在这种情况下,列表中“x,y,...,z” 替换为“x, x + d, x + 2d, x + 3d, ..., x + md,” 其中最后的点是语义点,而不是句法点。值是最大的数,使得x + md≤z如果d是正数,或者x + md≥z如果d为负数。

我认为是一个正整数,对于负值公式描述不正确(如评论中所述),因此在最后三种情况下,d=2 和=1,这导致序列2、2+d= 2,4。

如果你想要一个只包含(2)的列表,你可以使用:

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

考虑到列表语法的工作方式,我认为不可能有办法得到一个空白列表。

正如 percusse 在评论中指出的那样,列表中的第一个或两个元素是总是执行。要查看此内容,请看下面代码的一个版本,其中添加了一个命令来显示每次迭代的增量值和当前值。(这些是 中定义的长度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}

代码的格式化输出

相关内容