Arithmetics in LuaLaTeX

I have the following code.

\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{\directlua{fact(#1)}}
\begin{document}
\factorial{5}
\end{document}

This throws the error that attempt to perform arithmetic on a nil value. Where is the problem?

• Your lua function returns nothing if n!=0. So fact(n-1) is nil. – Alain Merigot Jul 18 at 11:21

With the code you posted, evaluating fact(5) causes the following expression to be evaluated by the Lua interpreter inside LuaTeX:

tex.sprint(5*fact(4))

which is

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

which is

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

which is

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

which is

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

which is

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

The first fact() call to return a value when the Lua interpreter evaluates fact(5) is thus fact(0). According to your definition of fact(), this evaluates to the Lua integer 1. Then 1*1 is evaluated, results in the Lua integer 1, and the next recursion level thus tries to evaluate 2*tex.sprint(1). This is where your code fails, since tex.sprint(1) evaluates to nil and 2*nil isn't a valid arithmetic expression (tex.sprint() prints contents to the DVI or PDF output, but as a Lua function, returns nil). Because of this error, the recursion stops.

You can fix the problem this way:

\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}{\directlua{printfact(#1)}}

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

which produces the following output (DVI or PDF): In this code, the fact() function always returns a Lua number (not nil), while printfact() writes the corresponding number to the TeX output file (DVI or PDF).

Here's my recommendation: Move the tex.sprint directive to the definition of the \factorial macro, and use return, not tex.sprint, to return numbers from the fact function.

Note also that since there are no TeX-special characters (such as #, %, and \) in the setup of the Lua function fact, one can define it via a \directlua call, as is done in the code below. No need, in this case, to load the luacode package.

\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{\directlua{tex.sprint(fact(#1))}}

\begin{document}
\factorial{5}
\end{document}
\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{\directlua{printfact(#1)}}

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