Метатаблица Lua, как перенаправить неопределенные функции?

У меня есть пустая таблица, которую я хочу использовать как «шлюз» для другого набора функций в другом месте.

tbl = {}

Я хочу передать вызываемые функции из этой таблицы в другое место в виде строки:

tbl.someMethod("hello")

Я пробовал это с ограниченным успехом.

hand = {
    __index = function(tbl, name)
      hand[name] = function(...) 
          passToSomewhere(name, ...)
      end
    end,
    __call = function(tbl, name, ...)
        hand[name](...)
    end
}
setmetatable(tbl, hand)
tbl.someFunction("hello!", someTbl, someNumber)

Как перенаправить неопределенную функцию через таблицу без ошибок?

Изменить: Подробнее

Я пытаюсь определить и вызвать функцию в таблице одним вызовом:

tbl = {}

hand = {
  __index = function(tbl, name)
    print(name)
    tbl[name] = function(...)
      print(...)
    end
  end
}
setmetatable(tbl, hand)

s,e = pcall(tbl.help,"banana","goat")
print(s)

s,e = pcall(tbl.help,"banana","goat")
print(s)

Этот код работает, но первый вызов вызовет ошибку, поскольку функция еще не определена.

Скажем, я хотел использовать библиотеку, которая, как я знаю, довольно часто обновляется и поддерживает совместимость моего сценария, и эта библиотека может отсутствовать на моем компьютере. Я хотел бы перенаправлять вызовы этой библиотеки через какой-либо интерфейс, но я все еще хочу иметь возможность вызывать функции таким же образом.

--For example I would like to call this function like this:
someLib.doSomething(name, age, telephone)

--Instead of passing it through another function:
someOtherLib.invoke("someLib.doSomething", name, age, telephone)

Это возможно?

Редактировать 2:

Спасибо @greatwolf!

Это мой рабочий тестовый код.

tbl = {}

hand = {
  __index = function(tbl, name)
    tbl[name] = function(...)
      return print(name, ...)
    end
    return rawget(tbl, name) 
  end
}
setmetatable(tbl, hand)

tbl.help("banana","goat")

person FortuneCookie101    schedule 18.01.2015    source источник
comment
Может быть, вам нужно return hand[name]? Не уверен, что это то, что вам нужно, но если ваш __index ничего не возвращает, вы в конечном итоге попытаетесь вызвать nil, и это вызовет ошибку.   -  person greatwolf    schedule 19.01.2015
comment
Разве более простой setmetatable(tbl,{__index=othertbl}) не работает?   -  person lhf    schedule 19.01.2015
comment
@greatwolf выглядит так, чтобы заставить это работать, мне нужно дважды вызвать неопределенную функцию, иначе она не будет определена. Я думаю, вы не можете сделать то, что я пытаюсь сделать за один раз.   -  person FortuneCookie101    schedule 19.01.2015
comment
Не совсем понятно, что вы пытаетесь сделать.   -  person greatwolf    schedule 20.01.2015
comment
@greatwolf Извините, я добавил больше деталей к своему вопросу.   -  person FortuneCookie101    schedule 20.01.2015


Ответы (1)


Хорошо, основываясь на ваших обновленных данных, вы хотите, чтобы lua перевела этот вызов.

someLib.doSomething(name, age, telephone)

в

someOtherLib.invoke("someLib.doSomething", name, age, telephone)

за кулисами. То, что у вас есть, почти готово, нужно только вернуть только что созданную функцию обратно:

__index = function(tbl, name)
  tbl[name] = function(...)
    return someOtherLib.invoke("someLib."..name, ...)
  end
  -- return tbl[name] works too, I used rawget to indicate 
  -- no further __index lookup should be done
  return rawget(tbl, name) 
end

Теперь, если ваш someOtherLib — это просто таблица функций, предложение lhf тоже сработает.

setmetatable(tbl, {__index = someOtherLib})

Теперь, если ваш someOtherLib предоставляет какой-то способ получить функцию, которую вы хотите вызвать, не вызывая ее на самом деле, __index может передать это, не создавая дополнительных оболочек закрытия.

__index = function(tbl, name)
  tbl[name] = someOtherLib.getFuncByName(name)
  return tbl[name]
end

Метаметод __call здесь не нужен.

person greatwolf    schedule 20.01.2015