[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Mutual requires
- From: Geoff Leyland <geoff_leyland@...>
- Date: Fri, 21 Dec 2012 19:19:31 +1300
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 }))