lua-users home
lua-l archive

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


On Sat, May 29, 2010 at 9:21 AM, duck <duck@roaming.ath.cx> wrote:
> The numeric 'for' loop is so simple, so quick, so easy to explain, so
> commonplace in programming (and so commonly provided in programming
> languages), and so jolly useful that I would like to suggest that we all
> agree to stop calling for its removal :-)

An excellent sentiment!

One can use macros to get some sugar over the basic for-loop.

For instance, this macro expands foreach x in t do into for _i=1,#t do
local x = t[_i].  It goes further; if the table parameter is an
expression then it synthesizes an enclosing block and creates a local
alias for that table expression. So slightly different code is
generated for these two cases:

t = {'one','two','three','four','five'}
foreach val in t do print(val) end

foreach k in {10,20,30} do print(k) end

Macros are often considered an 'unclean' solution to syntactical
clarity issues, but they can be very useful to _try out_ a proposed
syntax.

--- foreach.lua
macro.define ('foreach',nil,
    function (ls)
        -- getting
        local get = ls.getter
        local _,t1,name = get()
        local _,t2 = get()
        if t2 ~= 'in' or t1 ~= '<name>' then macro.error("expecting
'in' after single loop variable") end
        -- grab everything up to do
        local args = macro.grab_parameters('do','')
        if not args then macro.error("expecting 'do'") end
        args = args[1]
        -- putting
        local subst,put = macro.subst_putter()
        local function putn (n) put('<name>',n) end
        local tbl
        if #args > 2 then -- the table parameter is an expression;
factor out as an upvalue
            tbl = '_t'
            put 'do'; put 'local'; putn(tbl); put '='; put(args)
        else
            tbl = args[2]
        end
        put 'for'; putn '_i'; put '='; put('<number>',1); put ','; put
'#'; putn(tbl); put 'do';
        put 'local'; putn (name); put '='; putn(tbl); put '['; putn
'_i'; put ']'
        if #args > 2 then -- the for-loop is enclosed in a block
            macro.set_end_scanner ('end end',-1)
        end
        return subst
    end
)
-----

steve d.