lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, Nov 10, 2010 at 2:45 AM, Gopalakrishnan Subramani
<gopalakrishnan.subramani@gmail.com> wrote:
> Enum1 = ENUMERATION {
>     {1, "Forward"},
>    {2, "Backword"},
>
>    if BIDIERCTIONAL_SUPPORTED then
>       {3, "BiDirectional"},
>
>   {4, "None" }
> }

I have run into this same dilemma.  You want to use Lua in a manner,
not unlike PHP, to express hierarchical data structures that are
templatized with embeded Lua statement code.  Lua does the latter well
and the former ok (via tables), but they don't mix so
easily--statements not being allowed in expressions except at the
syntactic expense of an anonymous closure and even then their returned
expression lists are truncated to one value.  Furthermore, such logic
disappears upon evaluation (loadstring), complicating round-trip
loading/saving.  As seen in this discussion, there are also many
choices for how to define and evaluate the data syntax, keeping in
mind that Lua semantics may not exactly match your own data model
(e.g. Lua table keys being unordered and not repeating).  Such lack of
normalization may be worse than the "elements v.s. attributes" debate
in XML design, thereby distracting from the real problems at hand.

It may be that a pure data format, in the form of XML, Lisp
s-expressions, or plain nested Lua arrays is conceptually simpler and
closer to what you need.  Lisp has the simplest syntax (e.g. avoiding
commas).  The best of both world may be Lua code embedded in Lisp
data:

(enumeration
  (1 "forward")
  (2 "backward")
  # if BIDIRECTIONS_SUPPORTED then
    (3 "BiDirectional")
  # end
  (4 "None")
)

or Lua code (statements) embedded inside Lua data (expressions):

ENUMERATION {
  name = 'Enum1'
  1, "Forward" ;
  2, "Backword" ;
  if BIDIRECTIONAL_SUPPORTED then
    _T[3] = "BiDirectional" ;
  end
  4, "None" ;
}

which a preprocessor could translate to

ENUMERATION (function()
  local t = {}
  t.name = 'Enum1'
  t[1] = 1
  t[2] = "Forward"
  t[3] = 2
  t[4] = "Backward"
  if BIDIRECTIONAL_SUPPORTED then
    t[#t+1] = 3
    t[#t+1] = "BiDirectional"
  end
  t[#t+1] = 4
  t[#t+1] = "None"
  return t
)())

This same idea also will allow list comprehensions:

  t = {for x=1,10 do _T[#_T+1] = x*2 end}

i.e.

  t = (function() local t = {}; for x=1,10 do t[#t+1] = x^2 end; return t end)()

Incidentally, the problem of inserting expression lists in the middle
of a table constructor or function list (e.g. Rici's extended table
constructor patch) will also be handled:

  t = {a, b, for i,x in apairs(f()) _T[#_T+1] = x end, g()}
  h(a, b, for i,x in apairs(f()) _T[#_T+1] = x end, g())

and there's some interesting possibilities like redefining table
constructor semantics:

  local function ordered(t)
    t.keys = {}
    setmetatable(t, {__newindex = function(t,k,v) t.keys[#t.keys+1] =
k; rawset(t,k,v) end}) end
  end
  t = {do ordered(_T) end; x=1, x=2, y=3}
    -- t.keys is now {'x', 'x', 'y'}

and self-referential tables:

  t = {x = _T}

5.2?