我有以下代码。
\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
\directlua
luacode
\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}