lua-users home
lua-l archive

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


I'm trying to create a small local DSL for one of my tables in following form:

local Foo =
{
 ["Alpha"] = { op1 "a", op2 "b" };
 ["Beta"] = { op2 "a", op1 "b", op3 "c" };
}

I need to declare opN functions somewhere. As they wouldn't be used in
such context anywhere else, and they should have convenient short and
common names, I want to have their scope as local as possible.


<...snip...>

Two approaches to think about:

(1) If you can get something to execute before the table evaluator is initialized, then you can use the setfenv or similar trick. Here's
some code that seems to work:

	-- A few functions to set/unset an environment:
	function using(env)
        	local mt = getmetatable(_G)
        	if not mt then
        	        mt = {}
        	        setmetatable(_G,mt)
        	end
        	mt.__index = env
	end

	function stopusing()
        	local mt = getmetatable(_G)
        	if mt then mt.__index = nil end
	end

	-- Create an environment somewhere
	myenv = {}
	myenv.op1 = function(y) print("op1:",y) end
	myenv.op2 = function(y) print("op2:",y) end


	-- Now use it
	using(myenv)
	local Foo = {
	        ["Alpha"] = {op1 "a"};
	        ["Beta"] = {op1 "a", op2 "b"};
	}
	stopusing()

This assumes you are not using the global metatable __index for anything else.

The other approach is to delay evaluation until you've set up an environment. The only way I know how t do that is to put the code in to a string. You can imagine the syntax checking issues.

Something like this should work, though this code is not tested:

	-- Build an environment (not differences from above)
	myenv = {print=print, error=error} -- others as needed
	myenv.op1 = function print("op1",op1) end
	myenv.op2 = function print("op2",op2) end

	-- New version of function for using an environment
	function using(env)
		return function(code)
			local f = loadstring(code)
			setfenv(f,env)
			return f()
		end
	end


	-- Now use it
	local Foo = using(myenv) [[
                ["Alpha"] = {op1 "a"};
                ["Beta"] = {op1 "a", op2 "b"};
        ]]

Hope this helps!

  - Tom