![还有其他方法可以避免嵌套多项式中的名称冲突吗?](https://linux22.com/image/279376/%E8%BF%98%E6%9C%89%E5%85%B6%E4%BB%96%E6%96%B9%E6%B3%95%E5%8F%AF%E4%BB%A5%E9%81%BF%E5%85%8D%E5%B5%8C%E5%A5%97%E5%A4%9A%E9%A1%B9%E5%BC%8F%E4%B8%AD%E7%9A%84%E5%90%8D%E7%A7%B0%E5%86%B2%E7%AA%81%E5%90%97%EF%BC%9F.png)
约束
- 我想对内循环和外循环使用相同的名称。
- 我不愿意附加
@
并使用\makeatletter...\makeatother
。
是否有任何名称间距构造可供使用?
平均能量损失
由于两者发生冲突,因此以下代码不会产生正确的结果\i
。
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\def\Triangle(#1)#2{{\rput(#1){\multido{\i=0+1}{#2}{\multips(\i,0)(!.5 3 sqrt 2 div){\numexpr#2-\i\relax}{\pspolygon(1,0)(!.5 3 sqrt 2 div)}}}}}
\usepackage[nomessages]{fp}
\FPset\N{4}
\FPeval\Width{(N-1)*(N+2)/2+N}
\FPeval\Height{round(root(2,3)*N/2:6)}
\begin{document}
\begin{pspicture}(\Width,\Height)
\multido{\i=1+1}{\N}{\Triangle(!\i\space 1 sub \i\space 2 add mul 2 div 0){\i}}
\end{pspicture}
\end{document}
正确的输出如下。
答案1
通过在循环中为每个标识符使用唯一名称可以避免名称冲突。但是,在这种情况下,将参数直接传递给内部\multido
意味着它们在使用之前不会展开,此时也需要设置它们。“预展开”(声明包含参数展开版本的宏)有助于避免这种情况:
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}% http://ctan.org/pkg/multido
\SpecialCoor
\def\Triangle(#1)#2{%
\edef\firstarg{#1}\edef\secondarg{#2}% pre-expand #1 and #2
\rput(\firstarg){\multido{\i=0+1}{\secondarg}{\multips(\i,0)(!.5 3 sqrt 2 div){\numexpr\secondarg-\i\relax}{\pspolygon(1,0)(!.5 3 sqrt 2 div)}}}}
\usepackage[nomessages]{fp}% http://ctan.org/pkg/fp
\FPset\N{4}
\FPeval\Width{(N-1)*(N+2)/2+N}
\FPeval\Height{round(root(2,3)*N/2:6)}
\begin{document}
\begin{pspicture}(\Width,\Height)
\multido{\i=1+1}{\N}{\Triangle(!\i\space 1 sub \i\space 2 add mul 2 div 0){\i}}
\end{pspicture}
\end{document}
答案2
您可以使用\xintFor
包中的循环新工具. 人们不必担心迭代变量所使用的名称。
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{xinttools}
\SpecialCoor
% inside a macro, the # for an \xintFor must be doubled
%
\def\Triangle(#1)#2{{\rput(#1)%
{\xintFor* ##1 in {\xintSeq {0}{#2-1}}\do
{\multips(##1,0)(!.5 3 sqrt 2 div)%
{\numexpr#2-##1\relax}%
{\pspolygon(1,0)(!.5 3 sqrt 2 div)}}}}}
\usepackage[nomessages]{fp}
\FPset\N{4}
\FPeval\Width{(N-1)*(N+2)/2+N}
\FPeval\Height{round(root(2,3)*N/2:6)}
\begin{document}
\begin{pspicture}(\Width,\Height)
\xintFor* #1 in {\xintSeq{1}{\N}} \do
{\Triangle(!#1 1 sub #1 2 add mul 2 div 0){#1}}
\end{pspicture}
\end{document}
\Width
还\Height
可以实时计算xintexpr。
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{xintexpr}% loads xinttools automatically
\SpecialCoor
% inside a macro, the # for an \xintFor must be doubled
%
\def\Triangle(#1)#2{{\rput(#1)%
{\xintFor* ##1 in {\xintSeq {0}{#2-1}}\do
{\multips(##1,0)(!.5 3 sqrt 2 div)%
{\numexpr#2-##1\relax}%
{\pspolygon(1,0)(!.5 3 sqrt 2 div)}}}}}
\providecommand\firstofone [1]{#1}
\begin{document}
\def\N {4}
%
% we use \xintthenumexpr for the width as it guarantees
% integer format on output
%
% we use \firstofone to hide parentheses and other things from pspicture
%
\begin{pspicture}(\firstofone{\xintthenumexpr (\N-1)*(\N+2)/2+\N\relax},%
\firstofone{\xinttheexpr round(sqrt(3)*\N/2,6)\relax})
\xintFor* #1 in {\xintSeq{1}{\N}} \do
{\Triangle(!#1 1 sub #1 2 add mul 2 div 0){#1}}
\end{pspicture}
\end{document}
\firstofone
必须使用技巧来隐藏括号。出于某种原因,将整个 -essions 放在括号xintexpr
内不起作用pspicture
。括号里面 \xintexpr .. \relax
具有特殊含义,例如可以\xintthenumexpr{\xinttheexpr..\relax}\relax
对宽度这样做,但这确实很复杂。