Lua中使用长度运算符的问题

Lua中使用长度运算符的问题

这是我的 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}

我收到以下错误消息:

! Illegal parameter number in definition of \printdata.

LuaLaTeX 似乎无法理解#中的长度运算#data符。我在其他地方读到过,必须在其前面加上前缀:\string#data,但这仅在\newcommand定义之外有效。

我该如何解决这个问题?

答案1

foo.lua创建一个包含你的 Lua 代码的文件(例如):

function printeverything()
   data = {"a", "b", "c"}
   for i = 1, #data do
      tex.print(data[i])
   end
end

然后.tex您可以在您的文件中使用它:

\documentclass{article}

\directlua{dofile('foo.lua')}
\newcommand{\printdata}{\directlua{printeverything()}}

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

(您不需要使用 Lua 函数 - 您只需将函数的内容转储到您的文件中并定义\newcommand{\printdata}{\directlua{dofile('foo.lua')}}- 但如果您有多个 Lua 代码块,您可能不想为每个代码块创建单独的文件。)


解释:在使用 Lua 代码并将其放入.tex文件中时,迟早会遇到这个问题:TeX 引擎 (LuaTeX) 会读取.tex文件中的字符,假设某些类别代码,而字符(例如)#在 TeX 中具有特殊含义,而 Lua 代码中则不会有这些含义。有一种解决方法(运行texdoc luacode以​​查看luacode软件包文档),但在我看来,有充分的理由避免这些解决方法。正如该文档在第一段中所说的那样:

在介绍此包中的工具之前,我首先要强调的是,管理一段非平凡的 Lua 代码的最佳方法可能是使用外部文件并从 Lua 中获取它,如所引用的文档中所述。

所引文献(lualatex-doc.pdf说:

luacode软件包提供了不同程度的命令和环境,可帮助解决其中一些问题。但是,对于除琐碎的 Lua 代码之外的所有代码,更明智的做法是使用仅包含 Lua 代码定义函数的外部文件,然后加载它并使用其函数。例如:

\directlua{dofile("my-lua-functions.lua")}
\newcommand*{\greatmacro}[2]{%
\directlua{my_great_function("\luatexluaescapestring{#1}", #2)}}

我更喜欢将 Lua 代码放在单独的文件中的原因之一.lua是,当 Lua 代码放在单独的文件中时,您的编辑器可能会更好地对 Lua 代码进行语法突出显示.lua。(同样,如果 Lua 代码是单独的代码块,则在本网站上粘贴时可以获得更好的突出显示。)

答案2

您可以隐藏#到 TeX,同时使其适用于 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}

这将打印

篮球联赛

请注意,直接调用\directlua需要单个#。这里的加倍是因为#出现在定义中。

这是怎么回事?#是 TeX 的一个特殊字符。它是定义中参数的“前缀”(可以在 中单独使用\halign,但这不是这里的问题)。

当 TeX 吸收定义时,它不会解释宏和命令,但它会确保#后面跟着一个数字,数字取决于所定义的宏的参数数量。如果我们想传递#给宏的替换文本,我们需要将其加倍。参见参数中的双井号(数字符号,哈希字符)##1 是什么意思?了解详情。

这样,的替换文本\printdata实际上将包含单个#。但是,这#将在宏调用时进行解释,并且它将出现在错误的上下文中;但\string#会转换#为可打印字符,因此在执行时不会损害宏扩展\directlua

因此\string##data:加倍意味着 只\string#data存储在 的替换文本中\printdata。由于\directlua首先进行 TeX 宏扩展,Lua 将只看到#data(具有安全的#)。

相关内容