在以下测试中:
\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}