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 #).

Tags:

Lua

Luatex