从 lua 到 luatex 使用 Table 和 Metatable 的代码

从 lua 到 luatex 使用 Table 和 Metatable 的代码

接下来的代码来自《LUA 编程第四版》。图 20.1。集合的简单模块(元表和元方法部分)这里我仅使用函数 Set.new 的第二个代码

更确切地说,书中给出的代码是纯粹作为 lua 理解的部分。我的问题在于让它与 lualatex 一起工作,并了解我需要做哪些更改。

\documentclass{article} 
\usepackage{luacode}

\begin{document} 
\parindent=0pt  
\LuaCodeDebugOn
\luadirect{
local Set = {}
local mt = {}

function Set.new (l) 
  local set = {}
  setmetatable(set, mt)
  for _, v in ipairs(l) do set[v] = 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.intersection (a, b)
  local res = Set.new{}
  for k in pairs(a) do
    res[k] = b[k]
  end
  return res
end

function Set.tostring (set)
local l = {}    
    for e in pairs(set) do
        l[#l + 1] = tostring(e)
    end
return "{" .. table.concat(l, ", ") .. "}"
end 

return Set


  s1 = Set.new{10, 20, 30, 50}
  s2 = Set.new{30, 1}
  mt.__add = Set.union
  
  s3 = s1 + s2
  print(Set.tostring(s3))
  % mt.__mul = Set.intersection
  % print(Set.tostring((s1 + s2)*s1))          
}

\end{document}

在此代码中我当然尝试修改Set.tostring和使用tex.sprint 但在所有情况下我只看到nil结果。

我也不明白的是return Set后面的内容function Set.tostring (set) ,我必须承认元表的使用相当混乱。有多少个例子,就有多少个方法。

问题是:如何转换此代码至少以使其正确执行,以及更一般地讲,处理元表的正确方法是什么。

备注:ctan 的代码luaset.sty基于我提供的代码,但它带来了其他的复杂性,尤其是它没有帮助我理解。

答案1

最好将较大的 Lua 块放在文件中,以避免与 TeX catcodes 发生冲突。

set.lua

local Set = {}
local mt = {}

function Set.new (l) 
  local set = {}
  setmetatable(set, mt)
  for _, v in ipairs(l) do set[v] = 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.intersection (a, b)
  local res = Set.new{}
  for k in pairs(a) do
    res[k] = b[k]
  end
  return res
end

function Set.tostring (set)
local l = {}    
    for e in pairs(set) do
        l[#l + 1] = tostring(e)
    end
return "{" .. table.concat(l, ", ") .. "}"
end 

mt.__add = Set.union
mt.__mul = Set.intersection
 
return Set

然后您就可以使用\directlua它来进行调用(我通常不使用luacode包装器)

\documentclass{article} 


\begin{document} 
\parindent=0pt  

\directlua{Set=require('set')}

\typeout{=====}

\directlua{

  s1 = Set.new{10, 20, 30, 50}
  s2 = Set.new{30, 1}

  
  s3 = s1 + s2
  print(Set.tostring(s3))
 
  print(Set.tostring(s1*s2))  

  print(Set.tostring((s1 + s2)*s1))  
}

\typeout{=====}
\end{document}

生成:

=====
{1, 20, 30, 10, 50}
{30}
{20, 50, 30, 10}
=====

相关内容