在基本层面上,TeX 不提供 for 循环构造,但允许尾端递归,然而 Knuth\loop
在普通宏中定义了这一点。从那时起,程序员们就一直在使用他们自己的变体。
该ifthen
包提供了whiledo
循环,并且有一个forloop
宏。TikZ 也提供了类似的foreach
宏。
有没有一种规范的方式来forloop
用 LaTeX、TeX 和同类软件编写 a。你会如何编写以下内容?
\def\triangle#1{{\def\bull{}%
\count1=0
\loop
\edef\bull{$\bullet$\bull}
\ifnum\count1<#1
\advance\count1 by 1
\centerline{\bull}
\vskip-7.7pt
\repeat
\vskip 7.7pt\relax}}
这将产生一个由点组成的三角形
*
* *
* * *
正如在编程文本中常见的那样,您能以更好的方式重写它吗?
答案1
以下是我在 ConTeXt 中执行的操作:
\def\三角形#1% {\dorecurse{#1} {\centerline{$\dorecurse{\recurselevel}{{\bullet}}$}}} \starttext \三角形{4} \stoptext
周围的额外括号\bullet
是为了使其具有数学类 ord 而不是 bin。
答案2
一些 LaTeX3 解决方案。你可以将其作为复制品
\documentclass{article}
\usepackage{expl3,fixltx2e}
\begin{document}
\ExplSyntaxOn
\int_new:N \l_my_int
\prg_replicate:nn { 3 } {
\int_incr:N \l_my_int
\centerline { \prg_replicate:nn { \l_my_int } { \( \bullet \) } }
}
\ExplSyntaxOff
\end{document}
或者,while-do 方法:
\documentclass{article}
\usepackage{expl3,fixltx2e}
\begin{document}
\ExplSyntaxOn
\int_new:N \l_my_int
\intexpr_while_do:nn { \l_my_int < 4 } {
\int_incr:N \l_my_int
\centerline { \prg_replicate:nn { \l_my_int } { \( \bullet \) } }
}
\ExplSyntaxOff
\end{document}
我应该补充一点,复制系统存在限制expl3
(通常复制数以万计!)。因此,对于非常大的循环,while-do 可能更安全。
答案3
LuaTeX 解决方案可能如下所示:
\def\luatriangle#1{%
\directlua{
for i = 1,#1 do
tex.sprint(string.format("\\centerline{\%s}\\vskip-7.7pt", string.rep("$\\bullet$",i) ))
end
}}
这里只有一个小问题,因为宏包含\\
并且 TeX 对此有抱怨。因此解决方案(和建议)是将所有 Lua 代码放入单独的文件中,然后执行以下操作:
\def\luatriangle#1{%
\directlua{
dofile("loop.lua")
loop(#1)
}}
和 Lua 文件(loop.lua
):
function loop( count )
for i = 1,count do
tex.sprint(string.format("\\centerline{%s}\\vskip-7.7pt", string.rep("$\\bullet$",i) ))
end
end
不是最好的 LuaTeX 示例。丑陋的部分是 string.format(...) 行,但我认为循环部分非常易读。
答案4
Kees van der Laan 写了一篇题为“范式:循环”的文章,其中讨论了几种基于 TeX 的编写循环的方法。请参阅地图 17。