フック関数

基本的な構造を作ってから、後で動作を変えたいという場合がある。そういうときには、フック関数が便利である。Luaにはデバッグ用のフックがあるのでややこしいが、一般に(なのか知らないが)関数を呼び出したときに、ついでに実行する関数である。
フック関数を使えば、挙動が少しだけ異なるオブジェクトを作ろう、という場合に楽である。

-- 前処理フック関数
function prehook(fname,hfunc,env)
  if not env then env = _G end
  local f = env[fname]
  env[fname] = function(...)
    return f(hfunc(...))
  end
end

-- 後処理フック関数
function posthook(fname,hfunc,env)
  if not env then env = _G end
  local f = env[fname]
  env[fname] = function(...)
    return hfunc(f(...))
  end
end

Luaの場合は、こんな関数を用意すれば、任意の関数にフックすることができる。

test={}
function test.hoge()
  print("hoge")
end

function fuga()
  print("fuga")
end

prehook("hoge",fuga,test)
test.hoge()

--結果----
fuga
hoge
test={}
function test.add1(a)
  return a+1
end

function test.double(a)
  return a*2
end

function ten()
  return 10
end

posthook("ten",test.add1)
posthook("ten",test.double)
print(ten())

----結果----
22

環境をセットすればグローバル関数でなくてもフックできる。フックした関数は順番に実行し、次の関数に引数を引き継ぐようになっている。


この関数は便利だが、フックを解除したり、元の関数を取り出したりできないので注意が必要である。