[Tex/LaTex] Why does \luaexec work but the luacode environment doesn’t

lualuatex

The following code can be compiled by lualatex (Version beta-0.70.1-2011061410 (rev 4277)) correctly. But if I use \begin{luacode} ... \end{luacode} environment to replace the \luaexec{...} command, errors occur. Is this a bug?

! Extra }, or forgotten \endgroup.
<template> \unskip \hfil }
                          \hskip \tabcolsep \endtemplate 
l.19 \end{luacode}

? 
! Missing \endgroup inserted.
<inserted text> 
                \endgroup 
l.19 \end{luacode}

? 
! Missing } inserted.
<inserted text> 
                }
l.19 \end{luacode}

? 
! LaTeX Error: \begin{tabular} on input line 8 ended by \end{luacode}.
See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.19 \end{luacode}

? q

Here's an example

\documentclass[]{article}
\usepackage{luacode}
\usepackage[left=1cm,right=1cm]{geometry}

\begin{document}

\begin{center}

\begin{tabular}{lllllllll}

\luaexec{
  num=6
  for i=1,num do  
    for j=1,num do
    ixj='$'..i..'\\times'..j..'='..i*j..'$';
    tex.print(ixj)
    if(j<num) then tex.sprint('&') else tex.sprint('\\\\') end 
    end 
  end 
}

\end{tabular}
\end{center}

\end{document}

Best Answer

Each environment/macro is different. Each one redefines special characters differently.

For example, in your code example

\luaexec{
  num=6
  for i=1,num do  
    for j=1,num do
    ixj='$'..i..'\\times'..j..'='..i*j..'$';
    tex.print(ixj)
    if(j<num) then tex.sprint('&') else tex.sprint('\\\\') end 
    end 
  end 
}

you use \\. In latex \ is a special character. Latex processes the lua code block FIRST before lua gets chance to look at it. What this means is that if you have something like

\directlua{print('\n')}

Latex will parse that and see \ and try to do something with it. If \n is some latex macro it will attempt to expand it. One way to prevent latex from messing up lua code is to tell it not to expand it, such as

\directlua{print('\noexpand\n')}

In which case latex will see the \noexpand it not expand what is after it.

NOW, if we change the catcodes for \ and other special symbols we can stop latex from messing with our lua code. Sometimes this is good and sometimes this is bad.

For example

\newcommand{\mylatexmacro}{my text}
\directlua{print('\mylatexmacro')}

will print my text since latex will expand \mylatexmacro. BUT if we use

\newcommand{\mylatexmacro}{my text}
\luaexec{print('\mylatexmacro')} 

will print ?latexmacro where ? is whatever \m is in lua.

I tend to keep all my lua code separate from the latex code because there are generally just too many issues involved when you start getting in to it. For very simple stuff I'll use use inline lua code but code all my functions in a separate lua file that is included into the latex file.

Essentially the issue is that lualatex does not preprocess the tex file but simply provides a lua interpreter hooked into latex. lua code in latex is really latex code that is passed to the lua interpreter. When latex parses the code block it can mess up the code where lua won't understand what it is. e.g.,

\directlua{print('\\')}

does not print a \ because latex sees the \\ and tries to make a new line there then that new code is passed to the lua parser, which ends up not making any sense as lua code.