我想知道是否有人可以向我解释为什么
\documentclass{article}
\begin{document}
the standard approximation $\pi = \directlua{tex.sprint(math.pi)}$
\end{document}
一切正常,而
\documentclass{article}
\begin{document}
the standard approximation $\pi = \directlua{tex.sprint(string.format(' %.3f', math.pi))}$
\end{document}
抛出一个Undefined control sequence. \end{document}
这可能是非常基本的问题,但我就是不明白。提前谢谢
答案1
(百分比)符号%
对于 (La)TeX 和 Lua 来说都是特殊的,但用法却大不相同。在 (La)TeX 中,它是默认注释字符。在 Lua 中,它是模式匹配操作中的“魔法”字符之一。(Lua 的其他“魔法”字符是^$().[]*+-?
。)
该\directlua
指令是可扩展,在 TeX 特定意义上。这意味着 TeX 扫描 的参数以\directlua
查找任何宏;如果找到宏,TeX 将尝试扩展它们。在您的第二个示例中,当 (La)TeX 扫描
\directlua{tex.sprint(string.format(' %.3f', math.pi))}
它没有遇到任何 LaTeX 宏,但遇到了该%
字符,它将其解释为注释字符。因此,输入行末尾的所有内容都会被忽略,包括两个右括号和一个右花括号。这就是您收到错误消息的原因。
如何避免这两种互不相容的用途%
互相干扰?我想到了四种策略。
以不会被 LaTeX 不当处理的方式加载 Lua 代码。
将Lua代码放在外部文件中(通常以扩展名开头
.lua
,例如file.lua
),并通过指令将代码加载到LuaTeX中\directlua{dofile("file.lua")}
。在你的主 tex 文件中,加载lua代码包,它提供了称为
luacode
和的环境luacode*
,并将您的 Lua 代码放置在或luacode
环境中luacode*
。
不要这么做,而是在执行 Lua 代码时使用可以替代的\directlua
指令来处理。\%
%
加载
luacode
提供宏的包\luaexec
(用来代替),并使用反斜杠\directlua
“转义”所有实例,即,将它们重写为。例如,%
\%
\luaexec{tex.sprint(string.format('\%.3f', math.pi))}
定义一个名为 的宏,\percentchar
该宏扩展为 ,而%
TeX 不会将此字符解释为注释字符。这样就可以继续使用\directlua
。(非常感谢 Joseph Wright 提供此建议,并感谢 @egreg 提供指向 更简洁定义的指针\percentchar
!)
第四种方法是让
%
字符在 TeX 眼中不特殊。将以下指令 --\@percentchar
由 LaTeX“内核”定义;它输出 -- 的 catcode-12(“其他”)形式%
放在序言中:\makeatletter\let\percentchar\@percentchar\makeatother %% or: \begingroup\catcode`\%=12\relax\gdef\percentchar{%}\endgroup
然后,在文档正文中执行此指令:
\directlua{tex.sprint(string.format('\percentchar.3f', math.pi))}
回想一下,
\directlua
是可扩展的,也就是说,它将扩展\percentchar
为%
,这是 Lua 需要在string.format
函数中看到的字符。而且,由于这种形式的%
已被赋予 catcode 12(“其他”),因此它不会被 LaTeX 误解为注释字符——一切都很好。:-)虽然第四种方法乍一看似乎有点麻烦,但它具有不可否认的优点,即无需加载任何包(例如包
luacode
)或将 Lua 代码放在外部文件中即可实现。
究竟应该使用这四种方法中的哪一种,主要取决于在进行 Lua 调用时需要完成什么。如果只是简单指令的单个实例,第三和第四种方法可能最简单。如果 Lua 代码很长且很复杂,则几乎肯定会首选第一种和第二种方法。
以下示例说明了前三种可能性。
\RequirePackage{filecontents}
%% create an external file, to store Lua code
\begin{filecontents*}{aux.lua}
function printpi (n) -- n: number of decimal digits to be shown
tex.sprint ( string.format ( '%.'..n..'f' , math.pi ))
end
\end{filecontents*}
\documentclass{article}
\directlua{ dofile ( "aux.lua" ) } % load Lua code from external file
\usepackage{luacode} % load 'luacode' package
\begin{luacode}
function pi3() -- this function doesn't take an argument
tex.sprint ( string.format ( '%.3f' , math.pi ) )
end
\end{luacode}
\begin{document}
$\pi \approx \directlua{printpi(3)}$
$\pi \approx \directlua{pi3()}$
$\pi \approx \luaexec{tex.sprint(string.format('\%.3f', math.pi))}$
\end{document}
答案2
这是另一个想法。只需四舍五入math.pi
并显示结果。Lua 没有四舍五入到n
小数位的函数,但创建一个相对简单。下面的代码是 ConTeXt 的,但也应该可以直接转换为 LaTeX:
\startluacode
local floor, ceil = math.floor, math.ceil
math.Round = function(x, n)
local factor = math.pow(10, n or 0)
local y = x * factor
if x >= 0 then
y = floor(y + 0.5)
else
y = ceil(y - 0.5)
end
return y / factor
end
\stopluacode
\starttext
$π \approx \ctxlua{context(math.Round(math.pi, 3))}$
\stoptext
答案3
我们可以在 OpTeX 中做什么:
$\pi \approx \directlua{tex.sprint(string.format('\%.3f', math.pi))}$
\bye