lua-users home
lua-l archive

Re: event handler for table initialization

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


On Tue, Sep 21, 2010 at 1:54 PM, Javier Guerra Giraldez
<javier@guerrag.com> wrote:
> On Tue, Sep 21, 2010 at 2:47 AM, Nilson <nilson.brazil@gmail.com> wrote:
>> Using function calls and tables arguments to describe structures like
>> the example below
>>
>> Computer{
>>        brand = 'XYZ';
>>        Motherboard{
>>                Processor{type = 'Pentium'};
>>        Memory{size = '512MB'}
>>    };
>>    Harddisk{capacity='120GB'}
>> };
>>
>> will generate function calls in an order completely different of reading order.
>> In the example: Processor, Memory, Motherboard, Harddisk, Computer.
>
>
> when you want to reorder things in time, the usual answer is to pass
> around closures.  in your case, the easiest would be to write your
> functions as:
>
Javier, I think I didn't make myself clear (it was 5 am).
The actual issue is: when we make a function call using f { }, Lua
creates and initializes the table without notifying f. The function f
is called only when table is completely initialized.
So, although the function f, in many cases intents to describe the
table created, it is only a passive receiver of a defined table.
The idea is to allow a function f to be more active, receiving events
during the table initialization, eventually inserting or replacing
data and performing early detection of errors.
This could be done using a table event handler.
Example 1 (draft - beware: fresh ideas inside)
--
-- Implements an unquoted string feature
-- if does not exists a entry with name Name in _G, return the Name as string
--
local enum_mt = {}
enum_mt.__index = function (tab,Name)
 local value = rawget(tab,Name)
 if value == nil then return Name end
 return value
end
function enum{arg} -- <--- NEW: language change: using { } instead
of ( ) meaning a table event handler
 local evt = table.getevent -- NEW function to get the current event
 if evt ==nil then
	-- normal processing (usually an after processing)	
 return arg
 elseif evt.type = 'begin' then -- begin of table creation
 old_mt = getmetatable(_G);
 setmetatable(_G,enum_mt) -- installs unquoted string
 table.listen('e'); -- NEW: informs what to listen. here, listens
to end events (default behaviour)
 elseif evt.type = 'end' then -- end of table creation
 setmetatable(old_mt) -- resume the old one
 -- other usage
 --[[
 elseif evt.type = 'key' then -- new field with key defined
 print("with key",evt.key,evt.value)
 else if evt.type = 'field' then -- new field without a key
	print("without key",evt.key,evt.value)
 evt.key = 'autokey_'..evt.key -- prefix the keys with autokey_
 -- new idea: this event occurs when the compiler has a field value
composed by a simple name
 -- and cannot locate the name in the environments.
 -- It emulates a kind of table environment. evt.value has the
unresolved name.
 elseif evt.type = 'name' then
 return evt.value -- returns the name as value, implementing an
unquoted string
 --]]
 end
end
-- Usage. Note the absence of quotes
Color = enum{ red, black, white, yellow, blue }
Example 2
Parsing example
w = require('html.description')
w.html{
	w.head{ w.title { "Hello" }
	} --
	w.body{
	 onload = "onload()";
	 onsubmit = "/main.html"; -- this is an error because onsubmit is
not allowed here
 -- huge description of tables, divs etc.
	} -- body{
}
function w.body{ arg }
 local evt = table.getevent
 if evt == nil then
	-- normal processing (usually after processing)	
 return arg
 elseif evt.type = 'begin' then -- begin of table creation
 table.listen('k'); -- listen to key events
 elseif evt.type = 'key' then -- new field with key
 if evt.value = 'onsubmit' then
		error('Invalid argument: '..evt.value..' field#: '..evt.fieldno);
 -- early error detection: save time and memory and
eventually informs the line of file where the error occurred.
	end
 end
end
---
Nilson

AltStyle によって変換されたページ (->オリジナル) /