lua-users home
lua-l archive

Re: Mutual requires

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


On 21/12/2012, at 11:24 AM, Finn Wilcox <finnw@firecloudsw.co.uk> wrote:
> On 20/12/2012 19:59, Geoff Leyland wrote:
>> 
>> Attached. Note where "add" is required in expression.lua, after expression:new, but before the use of add. It's not quite like this in the actual code, but this kind of problem does turn up.
>> 
> I like this solution better. I'll update my stackoverflow answer.
Ultimately it didn't work for me. Or at least I couldn't get it to work. Or at least it got tricky enough that I tried something else.
Turns out that the example I gave didn't actually test that the "add" operator got an __add metamethod in time - for that I need to test (R.a + R.b) + (R.b + R.c). All R.a + R.b proved was that a "ref" operator had an __add, and ref wasn't in the require loop.
On 21/12/2012, at 11:11 AM, Kevin Martin <kev82@khn.org.uk> wrote:
> Have you considered using a lazy require, something like:
Well, it did turn out to be something like that in the end, only a bit more tailored to the case in hand. It's the last few lines of expression.lua. Same kind of thing that Steve and Finn suggested.
I still feel like there's a simpler solution somewhere.
----- expression.lua
local expression = {}
expression.__index = expression
local ops
function expression:new_op(o)
 o = o or {}
 o.__index = o
 for k, v in pairs(ops) do o[k] = v end
 return setmetatable(o, self)
end
function expression:new(o)
 return setmetatable(o or {}, self)
end
function expression.eval(exp, vars)
 local mt = getmetatable(exp)
 local f = mt and mt.__eval
 return (f and f(exp, vars)) or exp
end
local op_mods = setmetatable({}, { __index = function(t, k) t[k] = require(k) return t[k] end })
ops = { __add = function (a, b) return op_mods.add:new{a, b} end }
return expression
----- ref.lua
local ref = require("expression"):new_op()
function ref:__eval(vars)
 return vars[self[1]] or self
end
function ref:__tostring()
 return self[1]
end
return ref
----- add.lua
local expression = require("expression")
local add = expression:new_op(add)
function add:__eval(vars)
 local a = expression.eval(self[1], vars)
 local b = expression.eval(self[2], vars)
 if a == self[1] and b == self[2] then return self end
 return a + b
end
function add:__tostring()
 return tostring(self[1]) .. " + " .. tostring(self[2])
end
return add
----- main.lua
local expression = require("expression")
local ref = require("ref")
local R = setmetatable({}, { __index = function(t, k) return ref:new{k} end })
print(expression.eval((R.a + R.b) + (R.c + R.d), { b = 2 }))

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