在 LuaTeX 中将 tex.sprint 函数的输入传递给另一个函数时出现问题

在 LuaTeX 中将 tex.sprint 函数的输入传递给另一个函数时出现问题

我有包含以下代码的 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}

相关内容