LuaLaTeX 中的算术

LuaLaTeX 中的算术

我有以下代码。

\documentclass{article}
\usepackage{luacode} 
\begin{luacode}
function fact(n)
 if n == 0 then
          return 1
        else
           tex.sprint ( n * fact(n - 1) )
        end
      end
\end{luacode}
\newcommand\factorial[1]{\directlua{fact(#1)}}
\begin{document}
\factorial{5}
\end{document}

这会抛出一个错误,因为尝试对 nil 值执行算术运算。问题出在哪里?

答案1

使用您发布的代码,评估fact(5)会导致 LuaTeX 内部的 Lua 解释器评估以下表达式:

tex.sprint(5*fact(4))

tex.sprint(
  5*tex.sprint(
    4*fact(3)))

tex.sprint(
  5*tex.sprint(
    4*tex.sprint(
      3*fact(2))))

tex.sprint(
  5*tex.sprint(
    4*tex.sprint(
      3*tex.sprint(
        2*fact(1)))))

tex.sprint(
  5*tex.sprint(
    4*tex.sprint(
      3*tex.sprint(
        2*tex.sprint(
          1*fact(0))))))

tex.sprint(
  5*tex.sprint(
    4*tex.sprint(
      3*tex.sprint(
        2*tex.sprint(
          1*1)))))

因此,Lua 解释器求值时,第一个fact()返回值的调用fact(5)fact(0)。根据 的定义fact(),其求值为 Lua 整数1。然后1*1求值,结果为 Lua 整数1,因此下一个递归级别尝试求值2*tex.sprint(1)。这是代码失败的地方,因为tex.sprint(1)求值为nil并且2*nil不是有效的算术表达式(tex.sprint()将内容打印到 DVI 或 PDF 输出,但作为 Lua 函数,返回nil)。由于此错误,递归停止。

您可以通过这种方式修复此问题:

\documentclass{article}
\usepackage{luacode}

\begin{luacode}
function fact(n)
 if n == 0 then
    return 1
 else
    return n * fact(n - 1)
 end
end

function printfact(n)
  tex.sprint (fact(n))
end

\end{luacode}

\newcommand*{\factorial}[1]{\directlua{printfact(#1)}}

\begin{document}
\factorial{5}
\end{document}

产生以下输出(DVI 或 PDF):

在此处输入图片描述

在此代码中,fact()函数总是返回一个Lua数字(不是nil),而将printfact()相应的数字写入TeX输出文件(DVI或PDF)。

答案2

这是我的建议:将tex.sprint指令移动到宏的定义\factorial,并使用return,而不是tex.sprint,从函数返回数字fact

还要注意,由于Lua 函数的设置中没有 TeX 特殊字符(例如#%和) ,因此可以通过调用来定义它,如下面的代码所示。在这种情况下,无需加载包。\fact\directlualuacode

\documentclass{article}
\directlua{
function fact ( n )
   if n == 0 or n == 1 then
       return 1
   else
       return ( n * fact (n - 1) )
   end
end
}

\newcommand\factorial[1]{\directlua{tex.sprint(fact(#1))}}

\begin{document}
\factorial{5}
\end{document}

答案3

\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function printfact(n)
  if n == 0 then n = 1 end
  for i=2, n-1 do n=n*i end
  tex.sprint(n)
end
\end{luacode}
\newcommand*\factorial[1]{\directlua{printfact(#1)}}

\begin{document}
    \factorial{5}
\end{document}

相关内容