Lua Ropes |
|
Because strings are immutable objects in Lua, it is important to avoid creating them unnecessarily. Very often programs manipulate strings in order to create some textual output. One strategy is to avoid creating intermediate strings, and to output all the pieces of the final text in the right order. The appropriate datatype for this is the rope[1], where
rope ::= string | list of ropeIn other words, a rope is a tree whose leaves are strings. The important operation on trees is the tree-walk, applying a procedure to each leaf.
do local function walk(x,f) local typ, ok, bad = type(x),true local errmsg = "bad type (%s), %s" if typ == "string" then return pcall(f,x) elseif typ == "table" then local i,n = 1,#x while ok and i <= n do ok,bad = walk(x[i],f) i = i+1 end -- while return ok,bad else bad = errmsg:format(typ,typ and "" or "something undefined?") return nil,bad end -- if end -- function local mt = { push = function (self,x) local function f(y) if y and type(y) ~= "function" then self[#self + 1] =y return f elseif y then return function (z) return f(y(z)) end -- function end -- if end -- function y return f(x) end; -- function push walk = walk; flatten = function(self) local o = {} local f = function (x) o[#o + 1] = x end -- function self:walk(f) return table.concat(o) end; -- function } function rope() return setmetatable({}, {__index = mt}) end -- function end -- do t,x = rope(),rope() t:push (string.upper) "m" "r" (string.char) (32) "Smith" ; x:push [[ Good ]] [[morning]]; t:push (x) t:walk(io.write) --> Mr Smith Good morning print(t:flatten()) --> Mr Smith Good morning