Справочная таблица Lua внутри metatable - PullRequest
0 голосов
/ 04 июня 2018

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

function defGeneric()
    local function funcNumber(a)
        return 2*a^2
    end
    local function funcString(a)
        return a.." - test"
    end
    local returnTable={}
    returnTable["number"]=funcNumber
    returnTable["string"]=funcString
    return returnTable
end

И это прекрасно работает.Но сейчас я хочу сделать таблицу, которую эта функция возвращает вызываемой.Для иллюстрации, скажем, у нас есть v=defGeneric().В частности:

  1. Если v вызывается со строкой str, вернуть результат v["string"](str)
  2. Если v вызывается с номером n,вернуть результат v["number"](n)

Это очевидно работа для метатаблиц, поэтому я могу (в своей функции) добавить код для установки метатаблицы:

local metaTable = {
        __call = function (...) -- "call" event handler
            return  
        end
    }
setmetatable(returnTable,metaTable)

НоЯ не знаю, что бы я положил после этого заявления.Я не думаю, что могу ссылаться на returnTable, потому что эта таблица будет называться так:

v=defGeneric()
v("test")

И мне нужно сослаться на функцию "string" v (определенно может быть несколько defGeneric () таблицы в одной программе).

Я думаю, что ответ здесь может быть какой-то self трюк, но я не могу обернуться, как.Как мне обратиться к таблице метатаблицы из метатаблицы?

1 Ответ

0 голосов
/ 06 июня 2018

Первый аргумент, переданный функции __call, - это таблица, к которой она вызывается, в этом случае таблица возвращается из функции.Вы можете использовать type(a), чтобы получить тип аргумента в виде строки, чтобы вы могли сделать что-то вроде этого:

function defGeneric()
  local result = {
    ['number'] = function(a) return 2*a^2 end,
    ['string'] = function(a) return a.." - test" end
  }
  setmetatable(result, {
    __call = function(t,a)
      local f = t[type(a)]
      if f == nil then return "No handler for type "..type(a) end
    -- alternate:
    -- if f == nil and t['string'] ~= nil then return t['string'](tostring(a)) end

      return f(a)
    end
  })
  return result
end

local def = defGeneric()
print("string: "..tostring(def('sample string')))
print("number: "..tostring(def(5)))
print("table: "..tostring(def({})))
print("boolean: "..tostring(def(1 > 5)))

output

string: sample string - test
number: 50.0
table: No handler for type table
boolean: No handler for type boolean

альтернативный выход

string: sample string - test
number: 50.0
table: table: 0x18537e0 - test
boolean: false - test
...