lua-users home
lua-l archive

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


Quoth 刘小凡 <zhqqmao@gmail.com>, on 2010-01-27 17:53:59 +0800:
> Hello, everyone, sometimes I would like to change the run-time behavior of a
> function, usually I use dofile to achieve, but doing so will not change the
> previous reference,

I infer that what you mean is more precisely akin to the following:

There exist multiple code sources, each containing a definition for a
function (named) F.  In the past, you've loaded one source, then
loaded another source to overwrite the name F with a new definition,
but any places that have stored other references to the function
elsewhere won't use the new definition because they're no longer using
the name.  You want to be able to change the function in-place and
have all callers use the new definition.

> I am currently in luaV_settable function to add the following code:
> 
> / * When oldc and valc are the type of closure lua * /
> oldc-> l.p = valc-> l.p;

This is probably a very bad idea.  It has very unclean semantics.

There isn't a very good way to do what you're describing directly.
One thing you can do is create mutable proxy functions and have the
callers only see those.  If all the functions you describe are in a
table you control, you can use a metatable on that table to make the
indirection functions automatically.  Something along the lines of:

----------------------------------------
local function _make_indirect_fun(real_funs, k)
   return function(...)
	     return real_funs[k](...)
	  end
end

local INDIRECT_MT = {}

function INDIRECT_MT.__newindex(t, k, v)
   t.__actual[k] = v
   if type(v) == 'function' then
      t.__indirect[k] = _make_indirect_fun(t.__actual, k)
   end
end

function INDIRECT_MT.__index(t, k)
   local found = t.__actual[k]
   if type(found) == 'function' then
      return t.__indirect[k]
   else
      return found
   end
end

function indirect_module()
   return setmetatable({ __actual = {}, __indirect = {} }, INDIRECT_MT)
end

-- demonstration

local saved_sounds
function set_sounds(...) saved_sounds = {...} end
function do_sounds() for _,f in ipairs(saved_sounds) do f() end end

cow = indirect_module()
function cow.sound() print('Moooo!') end
chicken = indirect_module()
function chicken.sound() print('Cluck!') end

set_sounds(cow.sound, chicken.sound)
do_sounds()

-- cow is terrified now
function cow.sound() print('Noooo!') end

do_sounds()
----------------------------------------

(Dealing with the practically acceptable but slightly unclean hole in
the semantics regarding the __actual and __indirect keys is left as an
exercise for the reader.)

Adapt to your own environment as necessary, of course.  YMMV.

   ---> Drake Wilson