Problem using length operator in Lua
Make a file (say foo.lua
) containing your Lua code:
function printeverything()
data = {"a", "b", "c"}
for i = 1, #data do
tex.print(data[i])
end
end
Then in your .tex
file you can use it:
\documentclass{article}
\directlua{dofile('foo.lua')}
\newcommand{\printdata}{\directlua{printeverything()}}
\begin{document}
\printdata
\end{document}
(You don't need to use a Lua function — you could just dump the function's contents in your file and define \newcommand{\printdata}{\directlua{dofile('foo.lua')}}
— but if you have multiple chunks of Lua code you may not want to create separate files for each of them.)
Explanation: When working with Lua code, and putting it in your .tex
files, sooner or later you'll run into this issue: the TeX engine (LuaTeX) will read through the characters of your .tex
file assuming certain category codes, and characters like #
have special meanings in TeX that you don't intend in Lua code. There exists a way of working around this (run texdoc luacode
to see the documentation of the luacode
package), but IMO there are good reasons to do avoid these workarounds. As that documentation says in the very first paragraph:
Before presenting the tools in this package, let me insist that the best way to manage a nontrivial piece of Lua code is probably to use an external file and source it from Lua, as explained in the cited document.
The cited document (lualatex-doc.pdf
) says:
The
luacode
package provides commands and environments that help to varying degrees with some of these problems. However, for everything but trivial pieces of Lua code, it is wiser to use an external file containing only Lua code defining functions, then load it and use its functions. For example:\directlua{dofile("my-lua-functions.lua")} \newcommand*{\greatmacro}[2]{% \directlua{my_great_function("\luatexluaescapestring{#1}", #2)}}
One of the reasons I prefer putting Lua code in a separate .lua
file is that your editor probably does better syntax highlighting for the Lua code when it's in an separate .lua
file. (Similarly, you can get better highlighting when pasting the Lua code here on this website, if it's a separate code block.)
You can hide #
to TeX, while making it good for Lua:
\documentclass{article}
\newcommand{\printdata}{%
\directlua{
data = {"a", "b", "c"}
for i = \string##data, 1, -1 do
tex.print(data[i])
end
}%
}
\begin{document}
\printdata
\end{document}
This prints
cba
Note that a direct call to \directlua
would need a single #
. The doubling here is because #
appears in a definition.
What's this about? #
is a special character for TeX. It is the “prefix” for parameters in definitions (and can be used alone in \halign
, but it's not the problem here).
When TeX absorbs a definition it doesn't interpret macros and commands, but it ensures that #
is followed by a digit according to the number of arguments of the macro being defined. If we want to pass #
to the replacement text of a macro, we need to double it. See What is the meaning of double pound symbol (number sign, hash character) ##1 in an argument? for details.
In this way, the replacement text of \printdata
will actually contain a single #
. However, such #
would be interpreted at a call of the macro and it would appear in a wrong context; but \string#
transforms #
into a printable character, so it doesn't harm macro expansion when \directlua
is executed.
Thus \string##data
: the doubling means that just \string#data
is stored in the replacement text of \printdata
. Since \directlua
first does TeX macro expansion, Lua will just see #data
(with a safe #
).