1

The next code comes from the book "Programming in LUA 4th Edition". Figure 20.1. A simple module for sets (section Metatables and Metamethods) Here I only use the second code for the function Set.new

To be more precise, the code given in the book is the part understood purely as lua. My problem is in getting it to work with lualatex and understanding what changes I need to make.

\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}

In this code I tried of course to modify Set.tostring and use tex.sprint but in all cases I only see nil as a result.

What I also don't understand is the return Set just after function Set.tostring (set) and I must admit that the use of of metatables is quite anarchic. There are as many methods as there are examples.

The question is: how to transform this code at least to make it execute correctly and more generally what is the right way to handle metatables.

Remark : The code of luaset.sty on ctan is based on the code that I gave but it brings other complications and especially it does not help me to understand.

4
  • 1
    What is the code suppose to do? I just wanted to try it, but lualatex gives an error :1: <eof> expected near 's1'. \luadirect ... { \luacode@maybe@printdbg {#1} #1 } l.52 }
    – daleif
    Feb 16, 2023 at 11:31
  • @daleif with lua this code is supposed to give as result : print(Set.tostring(s3)) --> {1, 10, 20, 30, 50}but here with lualatex you have to change some lines tex.print instead of print etc . Feb 16, 2023 at 12:00
  • For me your code never gets that far (I outcommented the rest), it stops and complains at the s1 definition line. Doesn't it complain at your end?
    – daleif
    Feb 16, 2023 at 12:12
  • you have % so tex comments, you can mess with catcodes but it is best to put lua in a file.lua and just use \directlua{require('file')} Feb 16, 2023 at 12:16

1 Answer 1

2

It is better to put larger chunks of Lua in a file to avoid fighting 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

then you can use \directlua for the calls (I don't usually use luacode wrappers)

\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}

Produces:

=====
{1, 20, 30, 10, 50}
{30}
{20, 50, 30, 10}
=====
7
  • I finally have a problem with my editor. If I compile with zsh I get the result otherwise I have no pdf and no results in .log. Finally using tex.print to get the pdf. Can you explain me the role of return set? Feb 16, 2023 at 13:10
  • @AlainMatthes the code makes all the functions available in a table that it returns. in the require I saved that table as Set so could use Set.new in the later calls Feb 16, 2023 at 13:26
  • Is’t the only solution? Feb 16, 2023 at 13:34
  • @AlainMatthes is what the only solution? I just re-posted the code you posted in a form that # and % were safe, there are of course 1001 ways of accessing a safe # in tex but for muliple reason's I'd recommend having lua in lua files rather than in directlua chunks where the pre-expansion by tex makes copying off-the-shelf Lua "interesting" as you discovered. Feb 16, 2023 at 15:33
  • 1
    see lua.org/pil/15.2.html where this is explained (a global table as I suggest above is described in 15.1) @AlainMatthes Feb 16, 2023 at 16:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .