我有包含以下代码的 set.lua 文件。
local Set = {} --module
local mt = {} --metatable
function Set.new (l)
local set = {}
setmetatable(set, mt)
for _, v in ipairs(l)
do set[v] = true --table keys are elements of sets having boolean value true.
end
return set
end
function Set.union (a, b)
local res = Set.new{}
for k in pairs(a) do res[k] = true end
for k in pairs(b) do res[k] = true end
return res
end
function Set.tostring (set)
local l = {}
for e in pairs(set) do
if set[e] then
l[#l + 1] = tostring(e)
end
end
return "{" .. table.concat(l, ", ") .. "}"
end
return Set
然后是 luaset.sty 文件,其中包含以下代码。
\ProvidesPackage{luaset}
\RequirePackage{xkeyval}
\RequirePackage{amsmath}
\RequirePackage{luacode}
\begin{luacode*}
local st = require "set"
function union(s,t)
local s=st.new(s)
local t=st.new(t)
local v= st.union(s,t)
return tex.sprint(st.tostring(v))
end
function setprint(s)
s=st.new(s)
return tex.sprint("\\{" .. st.tostring(s) .. "\\}")
end
\end{luacode*}
\newcommand{\setPrint}[1]{\directlua{setprint(#1)}}
\newcommand{\setUnion}[2]{\directlua{union(#1,#2)}}
\endinput
使用LuaTeX或LuaHBTeX编译的Tex文件具有以下输入。
\documentclass{article}
\usepackage{luaset}
\begin{document}
\def\S{{'a','b','c',10}} % declaring set S
\def\T{{'d','e','f',10,20}} % declaring set T
\(S= \setPrint{\S}\)\\ % printing set S
\(T=\setPrint{\T}\) \\ % printing set T
\def\V{\setUnion{\S}{\T}} % union of S and T
\(V= \setPrint{\V}\) % printing set V
\end{document}
这已编译。但是 TeX 文件中的最后一行未提供预期的输出。请注意,它仅\V
提供了正确的字符串集。因此,为了解决这个问题,我需要修改文件set.print
中的函数luaset.sty
。我不知道要进行哪些更改。任何有关这方面的帮助都将不胜感激。谢谢。
答案1
混合 TeX 宏和 Lua 值不是一个好主意。这总是会带来麻烦,因为你必须以某种方式从字符串中删除格式,以使它们可以被 Lua 理解,而这几乎总是会出错。
让我提出这个替代方案。首先,我将集合解析为 TeX 中的字符串,这也解决了您之前要求的 XY 问题:Lua LaTeX 中为全局环境设置 Metatable 时出错
然后我实现了与您的类似的集合操作,但是除了__tostring
返回 Lua 表而不是格式化的字符串之外的每个集合操作。
宏接口不使用宏来存储集合运算的结果,而是用户传入名称,然后使用名称在 Lua 端跟踪集合。
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
Set = {} -- module
local mt = {
__tostring = function(self)
return "\\{" .. table.concat(table.sortedkeys(self), ", ") .. "\\}"
end
}
function Set.new(str)
str = str or ""
local set = {}
for v in utilities.parsers.iterator(str) do
set[v] = true
end
return setmetatable(set, mt)
end
function Set.union(...)
local sets = table.pack(...)
local union = {}
for _, set in ipairs(sets) do
for e in pairs(set) do
union[e] = true
end
end
return setmetatable(union, mt)
end
sets = {} -- global set registry
\end{luacode*}
\newcommand\setNew[2]{%
\directlua{%
sets[\luastringN{#1}] = Set.new(\luastringN{#2})
}%
}
\newcommand\setUnion[3]{%
\directlua{%
sets[\luastringN{#1}] = Set.union(sets[\luastringN{#2}],
sets[\luastringN{#3}])
}%
}
\newcommand\setPrint[1]{%
\directlua{tex.sprint(tostring(sets[\luastringN{#1}]))}%
}
\begin{document}
\setNew{S}{a,b,c,10}
\setNew{T}{d,e,f,10,20}
\setUnion{R}{S}{T}
\setPrint{S}\par
\setPrint{T}\par
\setPrint{R}
\end{document}