Lua Ropes

lua-users home
wiki

Difference (from prior major revision) (minor diff, author diff)

Changed: 3c3
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, where
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

Changed: 7c7
{{{
{{{!Lua

Changed: 9,25c9,24
local walk -- recursion ahead
walk = function (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 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

Changed: 27,48c26,46
local mt = {
push = function (self,x)
local f -- recursion ahead
f = function (y)
if y and type(y) ~= "function" then
table.insert(self,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) table.insert(o,x) end -- function
self:walk(f)
return table.concat(o)
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

Changed: 51,55c49,51
rope = function ()
local t = {}
setmetatable(t, {__index = mt})
return t
end -- function
function rope()
return setmetatable({}, {__index = mt})
end -- function

Removed: 65,68d60

Sorry - have not got the hang of how to control indentation in the wiki display yet.

Note that the "local function" syntax, which supports recursive definitions, can be used within blocks. There is no need for a separate declaration and definition.

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 rope 
In 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

RecentChanges · preferences
edit · history
Last edited June 4, 2007 6:43 pm GMT (diff)