lua-users home
lua-l archive

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



If runtime speed is not #1 priority, a concept I was toying around the other day could be useful here?

It allows one to 'combine' N number of variable argument lists together, either into a table (without the empty call at end) or into a varlist (with the terminating '()' call).

There's multiple variations of the theme, based on whether one wants to allow empty varlists, etc. This is provided only as a toy, sample, free for your modding and blame.

( As usual with my tools, and toys, I threw it aside! ;)

-asko


-----
-- ...= combine(...)(...)(...)(...)(...)(...)(...)(...)()
--
-- Normally, Lua does not allow combining parameter lists; only the _last_ parameter is allowed -- to carry N values further. Those in between the parameter list are truncated to their first
-- value.
--
-- This function changes that, allowing you to join together any number of parameter lists,
-- each carrying any (1..N) number of parameters.
--
-- The catch? There needs to be an empty list call, to end the worm. This will cause you to -- gain a parameter list; otherwise, you're gaining a table with the collected values. This -- also means, none of the intermediate calls may be empty, or you'll get screwed.
--
local combine_meta= {
    __call=
        function( self, ... )
            local n= select('#',...)
            if n==0 then
                return unpack(self)     -- terminating ()
            else
                for i=1,n do
                    self[#self+1]= select(i,...)
                end
                return self
            end
        end }

local function combine( ... )
    local t= {...}
    setmetatable( t, combine_meta )
    return t
end

local t= { combine(1,2)(3,4)(5)() }
assert( #t==5 )
for k,v in ipairs(t) do assert(k==v) end



Karel Tuma kirjoitti 9.11.2006 kello 22.13:

hi,

this is already easily doable,
table constructor just for tab = { func() }
fills the table with *all* the return values of a function.
all you have to do is "flatten" the introduced tree structure.
in lots of data describing i'm doing in lua, i've to use the "define and
normalize" paradigm to establish functionality i need.
note that flatten() can be called from a __newindex metamethod
defined on the environment of loadfile("config.lua").
also doing some sanitary checks during __newindex step might be good idea.

here's somewhat simplified example
----------------------------
function b()
        return "foo", "bar"
end

t = {
        a = 1,
        { b() },
        c = 2,
}

-- this must be done two-phase using temporary table,
-- modifying table keys while in ipairs() is just too tricky for us
function flatten(t)
        local tmp = {}
        for si,sv in ipairs(t) do
                for _,v in ipairs(sv) do
                        table.insert(tmp, v)
                end
                t[si] = nil
        end
        for _,v in ipairs(tmp) do
                table.insert(t, v)
        end
end
flatten(t)
for k,v in pairs(t) do
        print(k,v)
end
--------------------------
$ lua t.lua
1       foo
2       bar
c       2
a       1


On Thu, Nov 09, 2006 at 07:05:56PM +0100, Mark Hamburg wrote:
When using Lua for more or less data description tasks, I'm frequently finding myself wishing for a splice operator that would allow one to use all of the results of a function when building a table. My particular example comes up when building view descriptions. For example, the following works
in that makeChildren can return all of the items that it wants to:

    column{
        spacing = 10,
        makeChildren()
    }

But the following does not work:

    column{
        spacing = 10,
        makeChildren(),
        view{
            title = "footer",
        }
    }

Now I only get the first child. Coding around this requires using temporary
variables:

    local t = makeChildren()
    t.spacing = 10
    t[ #t + 1 ] = view{ title = "footer" }
    column( t )

That approach doesn't work well when nested down within the description because I have to move the work with t out of the structural description
which then makes the construction process harder to follow.

I'm thinking that something along the following lines would be useful:

    column{
        spacing = 10,
        $makeChildren(),
        view{
            title = "footer",
        }
    }

Where the $ means that we take all of the results from the function rather than just the first. (And if it has no results, we also reflect that.) I
would also be quite open to other syntaxes.

Mark