Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/LUA/Comprehensions1.lua.html -- http://anggtwu.net/LUA/Comprehensions1.lua -- (find-angg "LUA/Comprehensions1.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Date: 2025sep13 -- -- These classes can be used to show how set comprehensions are -- calculated step-by-step, using trees drawn as LaTeX matrices like -- the ones in: -- -- (mpgp 9 "comprehension-tables") -- (mpga "comprehension-tables") -- -- «.tocurly» (to "tocurly") -- «.tocurly-tests» (to "tocurly-tests") -- «.MTree» (to "MTree") -- «.MTree-tests-defs» (to "MTree-tests-defs") -- «.MTree-tests» (to "MTree-tests") -- «.Filter» (to "Filter") -- «.Comprehension» (to "Comprehension") -- «.Comprehension-tests» (to "Comprehension-tests") -- «tocurly» (to ".tocurly") tocurly_prefix = "" tocurly_prefix = "\\" tocurly = function (L, p) p = p or tocurly_prefix return p.."{"..mapconcat(tostring, L, ",")..p.."}" end -- «tocurly-tests» (to ".tocurly-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Comprehensions1.lua" = tocurly(seq(2,10,3)) = tocurly(seq(2,10,-1)) tocurly_prefix = "" = tocurly(seq(2,10,3)) --]] -- __ __ _____ -- | \/ |_ _| __ ___ ___ -- | |\/| | | || '__/ _ \/ _ \ -- | | | | | || | | __/ __/ -- |_| |_| |_||_| \___|\___| -- -- «MTree» (to ".MTree") -- Base on: (mpgp 9 "comprehension-tables") -- (mpga "comprehension-tables") -- (mpga "comprehension-tables" "Stop") -- -- MTrees are used to show how set comprehensions -- can be calculated using trees. -- The "M" means "LaTeX <M>atrix", -- and if m is an MTree then m:totex() -- generates the body of a LaTeX matrix, -- in a format like this: -- -- x & 6-x & \{x,...,6-x\} & y & (x,y) \\\hline -- 1 & 5 & \{1,2,3,4,5\} & 1 & (1,1) & -- & & & 2 & (1,2) & -- & & & 3 & (1,3) & -- & & & 4 & (1,4) & -- & & & 5 & (1,5) & -- 2 & 4 & \{2,3,4\} & 2 & (2,2) & -- & & & 3 & (2,3) & -- & & & 4 & (2,4) & -- 3 & 3 & \{3\} & 3 & (3,3) & -- 4 & 2 & \{\} & \Stop & -- 5 & 1 & \{\} & \Stop & -- MTree = Class { type = "MTree", new = function (o) return MTree {[0]=o} end, _ = function (o) return MTree {[0]=o} end, from = function (o) if otype(o) == "MTree" then return o end if type(o) == "number" then o = tostring(o) end if type(o) == "string" then return MTree {[0]=o} end local T = MTree(map(MTree.from, o)) T[0] = o[0] return T end, tosyntree = function (o) return MTree.from(o):tosyntree() end, totexrect = function (o) return MTree.from(o):totexrect() end, torect = function (o) return MTree.from(o):torect() end, totex = function (o) return MTree.from(o):totex() end, __tostring = function (o) return MTree.from(o):tostring() end, __index = { -- -- Generate the top line with the column names, as a Rect. top_rect_tex = function (T) return T:top_rect(" & ", " \\\\\\hline") end, top_rect_syntree = function (T) return T:top_rect(" | ", "") end, top_rect = function (T,sep,post) if not T.columnnames then return Rect {} end local line = table.concat(T.columnnames, sep)..post return Rect {line} end, -- -- The default :tostring() method, that uses SynTrees. tostring = function (T) return T:torect():tostring() end, torect = function (T) return T:top_rect_syntree() / T:tosyntree():torect() end, tosyntree = function (T) return SynTree.from(T) end, -- -- The :totex() method generates the body of a LaTeX matrix. -- The matrix is generated from left to right, recursively. totex = function (T) return T:totexrect():tostring() end, totexrect = function (T) return T:top_rect_tex() / T:totexrect_LR() end, totexrect_R = function (T) local R = Rect {} for _,node in ipairs(T) do for _,line in ipairs(MTree.totexrect(node)) do table.insert(R, line) end end return R end, totexrect_LR = function (T) local R = T:totexrect_R() if not T[0] then return R end if #T==0 then return Rect {T[0].." \\\\"} end local Ltop = format("%s & ", T[0]) local Lblank = Ltop:gsub("[^&]", " ") local L = Ltop / Rect.rep(Lblank, #R-1) return L..R end, -- -- Methods that add elements and subtrees to an MTree. -- These methods are very tricky! See MTree_test{1,2,3} below. add_ = function (T,o) local subTree = MTree.new(o) table.insert(T,subTree) return subTree end, addstop = function (T) T:add_("\\Stop") end, addfalse = function (T) T:add_("\\False"):addstop() end, addtrue = function (T) return T:add_("\\True") end, addstopifempty = function (T) if #T == 0 then T:addstop() end end, setcolumnnames = function (T,cols) T.columnnames = cols; return T end, }, } --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Comprehensions1.lua" T = MTree.new() T:add_(1) PPV(T) do local T = T:add_(2) T:add_(23) T:add_(24) end T:add_(5) = T = T:totex() PPV(T) T = MTree.new() for x=1,2 do local T = T:add_(x) for y=3,4 do local T = T:add_(y) end end = T = T:totex() T.columnnames = {"x","y"} = T = T:totex() PPV(T) --]] -- __ __ _____ _ _ -- | \/ |_ _| __ ___ ___ | |_ ___ ___| |_ ___ -- | |\/| | | || '__/ _ \/ _ \ | __/ _ \/ __| __/ __| -- | | | | | || | | __/ __/ | || __/\__ \ |_\__ \ -- |_| |_| |_||_| \___|\___| \__\___||___/\__|___/ -- -- «MTree-tests-defs» (to ".MTree-tests-defs") -- These tests were hand-written, but the class `Comprehension', -- defined below, generates code similar to these examples. MTree_test0 = function () local T = MTree.new() for x=1,2 do for y=3,4 do for z=5,6 do T:add_(format("(%s,%s,%s)", x,y,z)) end end end return T end MTree_test1 = function () local T_ = MTree.new() for x=1,2 do local Tx = T:add_(x) for y=3,4 do local Ty = T:add_(y) for z=5,6 do local Tx = T:add_(z) end end end return T_ end -- { x in {1,...,5}, y in {x,...,6-x} ; (x,y) } -- \-/ -- lim -- \---------/ -- range -- MTree_test2 = function () local T = MTree._() for x=1,5 do local lim = 6-x local range = tocurly(seq(x,lim)) local T = T:add_(x) -- also called T local T = T:add_(lim) -- also called T local T = T:add_(range) -- also called T, etc for y=x,6-x do local T = T:add_(y) local T = T:add_(format("(%s,%s)",x,y)) end T:addstopifempty() end T.columnnames = {"x", "6-x", "\\{x,...,6-x\\}", "y", "(x,y)"} return T end -- «MTree-tests» (to ".MTree-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Comprehensions1.lua" = MTree_test0() = MTree_test0():totex() T3 = {[0]=3, 5, 6} T4 = {[0]=4, 5, 6} T1 = {[0]=1, T3, T4} T2 = {[0]=2, T3, T4} T0 = { T1, T2} T = MTree.from(T0) T.columnnames = {"x","y","z"} = T = MTree.from(T0) = MTree.totex(T0) = MTree.totex(T) T = MTree_test1() = T; = T:totex(); tocurly_prefix = "" T = MTree_test2() = T; = T:totex(); tocurly_prefix = "\\" T = MTree_test2() = T; = T:totex(); --]] -- «Filter» (to ".Filter") MTree_test3 = function () local T = MTree.new() for x=1,5 do local lim = 6-x local range = tocurly(seq(x,lim)) local T = T:add_(x) -- also called T local T = T:add_(lim) -- also called T local T = T:add_(range) -- also called T, etc for y=x,6-x do local T = T:add_(y) local T = T:add_(format("(%s,%s)",x,y)) end T:addstopifempty() end T.columnnames = {"x", "6-x", "\\{x,...,6-x\\}", "y", "(x,y)"} return T end --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Comprehensions1.lua" = MTree_test3() --]] -- ____ _ _ -- / ___|___ _ __ ___ _ __ _ __ ___| |__ ___ _ __ ___(_) ___ _ __ -- | | / _ \| '_ ` _ \| '_ \| '__/ _ \ '_ \ / _ \ '_ \/ __| |/ _ \| '_ \ -- | |__| (_) | | | | | | |_) | | | __/ | | | __/ | | \__ \ | (_) | | | | -- \____\___/|_| |_| |_| .__/|_| \___|_| |_|\___|_| |_|___/_|\___/|_| |_| -- |_| -- -- «Comprehension» (to ".Comprehension") Comprehension = Class { type = "Comprehension", new = function () return Comprehension {prog = Rect{}} end, fromcommands = function (commands) return Comprehension.new():runcommands(commands):Function() end, __tostring = function (co) return co.prog:tostring() end, __index = { pre = function (co,r1) co.prog = torect(r1)/co.prog return co end, post = function (co,r2) co.prog = co.prog/torect(r2) return co end, -- Column = function (co,expr) return co:pre(format("local T = T:add_(%s)", expr)) end, Local = function (co,vardef,var) if var then co:Column(var) end return co:pre(format("local %s", vardef)) end, For = function (co,varin,var) if var then co:Column(var) end co.prog = torect(format("for %s do", varin)) / (" " .. co.prog) / torect("end") / torect("T:addstopifempty()") return co end, -- var = function (co,str) return varin:match("^%s*([0-9A-Za-z_]+)") end, Gen = function (co,varin) return co:For(varin, co:var(varin)) end, Expr = function (co,expr) return co:Column(expr) end, -- Function = function (co) if co.columnnames then local body = mapconcat(mytostring, co.columnnames, ", ") co:pre(format("T.columnnames = {%s}", body)) end co:pre ("local T = MTree.new()") co:post("return T") co.prog = "function ()" / (" " .. co.prog) / " end" return co end, Colnames = function (co, ...) co.columnnames = {...} return co end, -- splitcommand = function (co,line) return VTable(map(bitrim, split(line, "([^|]+)"))) end, runcommand = function (co,line) local parts = co:splitcommand(line) co[parts[1]](co, unpack(parts,2)) return co end, runcommands = function (co,lines) if type(lines) == "string" then lines = splitlines(lines) end for i=#lines,1,-1 do local line = lines[i] line = line:gsub("%-%-.*", "") line = bitrim(line) if line ~= "" then co:runcommand(line) end end return co end, eval = function (co) return expr(tostring(co))() end, }, } -- «Comprehension-tests» (to ".Comprehension-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Comprehensions1.lua" tocurly_prefix = "" tocurly_prefix = "\\" = MTree_test2() co = Comprehension.new() = co:Column ('format("(%s,%s)",x,y)') = co:For ('y=x,6-x', 'y') = co:Local ('range = tocurly(seq(x,lim))', 'range') = co:Local ('lim = 6-x', 'lim') = co:For ('x=1,5', 'x') = co:Function() co = Comprehension.new() = co:splitcommand "Local | range = tocurly(seq(x,lim)) | range" = co:runcommand "Local | range = tocurly(seq(x,lim)) | range" cmds = [=[ Colnames | x | 6-x | \{x,\ldots,6-x\} | y | (x,y) For | x = 1,5 | x Local | lim = 6-x | lim Local | range = tocurly(seq(x,lim)) | range For | y = x,6-x | y Column | format("(%s,%s)",x,y) ]=] co = Comprehension.fromcommands(cmds) = co = co:eval() = co:eval():totex() --]==] -- Local Variables: -- coding: utf-8-unix -- End: