PGF \foreach 的一个意外结果

PGF \foreach 的一个意外结果

以下来自 PGF 手册 2.40 第 508 页的示例给出了我意想不到的结果。

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

在此处输入图片描述

我期望看到bc,,,,bdbecdcede期望

以下给出预期的输出:

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

在此处输入图片描述

我猜\foreach

我自己的\newforeach给了

在此处输入图片描述

使用代码

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

最后一个输出正是我所期望的\foreach。遗憾的是,\newforeach尚未发布,因为它仍在测试中。您可以索取并参与测试。

答案1

如果你试试

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

那么一切都很好:问题在于\foreach代码处理字母迭代的方式存在错误。相关代码是

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

这里,#1是用于保存将要打印/使用的临时变量\x,,\yETC。它是一个数字,但上面的代码将其转换为字母。但是,上面的代码并没有正确地做到这一点:所有这些\expandafters 都没有扩展\pgfutil@tempcnta,而这实际上是需要的。对我来说

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

解决了该问题,因为字母现在已经“烘焙”好了。

(我没有彻底追踪它,但我的猜测是,在明确的迭代列表中,不涉及数字部分,因此只有在使用...符号时才能看到这一点。)


在这里完全禁用转换是非常有启发性的:

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

这表明\foreach第一种情况的处理方式与所有其他情况是分开的。我不确定这是否是一个好计划,因为它留下了行为变化的风险。

相关内容