12

This is my MWE:

\documentclass{article}

\newcommand{\printdata}{%
  \directlua{
    data = {"a", "b", "c"}
    for i = 1, #data do
      tex.print(data[i])
    end
  }
}

\begin{document}
  \printdata
\end{document}

I get the following error message:

! Illegal parameter number in definition of \printdata.

LuaLaTeX doesn't seem to understand the length operator # in #data. Somewhere else I read that you must prefix it thus: \string#data, but this only works outside the \newcommand definition.

How can I fix this problem?

  • 1
    At minimum you need to use luacode environment, but in general I strongly recommend putting lua code in separate files and including with dofile. – ShreevatsaR Oct 25 '17 at 0:02
  • 2
    Your statement, "LuaLaTeX doesn't seem to understand the length operator # in #data", is somewhat misleading. The issue is that the argument of \directlua is expanded (in the TeX sense of the word) before the Lua code is passed to Lua for further processing. And, because "#data" is not a valid expression according to TeX's syntax rules, you get a TeX-based error message, ! Illegal parameter number.... – Mico Oct 25 '17 at 4:53
14

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

  • Great! Thanks. I got it working now. This issue of token expansion and escape codes is always tormenting me, as I have never been able to wrap my head fully around it. Using the dofile function circumvents some of the problems related to it. – NVaughan Oct 25 '17 at 2:50
  • 1
    @NVaughan Glad it worked. Yes dofile helps, and more generally LuaTeX helps a lot with avoiding having to worry about token-expansion: you can pass arguments to Lua functions as in typical programming languages, and so on. Good luck! – ShreevatsaR Oct 25 '17 at 2:58
7

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

  • Thanks. Could you explain to me what exactly does \string## do, please? I haven't been able to find any documentation on it. – NVaughan Oct 25 '17 at 14:12
  • 1
    @NVaughan See edit – egreg Oct 25 '17 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.