编写 for 循环宏的规范方法是什么?

编写 for 循环宏的规范方法是什么?

在基本层面上,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

相关内容