2016-11-17 10 views
1

Целью является сопоставление ключа таблицы со значением, зависящим от ключа.Доступ к ключу в значении (правой стороне) привязки клавиш таблицы в Lua

example = { ["dummy"] = this .. " example" } 
print example.dummy -- print "dummy example" 

Адрес this является ключевым словом для ссылки на ключ. Есть ли способ сделать это в Lua?

ответ

2

Невозможно сделать это напрямую.

Вы могли бы сделать некоторые предварительной обработки:

example = { ["dummy"] = "{THIS} example" } 
for k,v in pairs(example) do 
    example[k]=v:gsub("{THIS}",k) 
end 
print(example.dummy) 
+0

Ну, это сработает для моего приведенного примера, так что это правильный ответ. Однако я имел в виду использование 'this' в качестве параметра анонимной функции, затронутой ключом, например' example = {["dummy"] = function (k = this) return k .. "example" end' , – psychoslave

+0

@psychoslave, при предварительной обработке, если 'v' является функцией, выполните пример [k] = v (k)'. – lhf

+0

@psychoslave Почему бы просто не пропустить ключ напрямую при вызове? – warspyking

1

Это не возможно, чтобы иметь как чистое выражение, как:

t = { foo = this .. ' bar' } 

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

Возможно, что реализуется некоторый уровень косвенности с использованием metatables и функций, но это довольно сложно. Здесь мы проводим оценку времени выборки. Вы также можете пересчитать результаты.

local function indirect_table() 
    local uptable = {} 

    return setmetatable({}, { 
     __index = function (self, key) 
      local value = uptable[key] 

      return type(value) == 'function' and uptable[key](key) or value 
     end, 
     __newindex = function (self, key, value) 
      uptable[key] = value 
      --[[precompute, with no need for an uptable, or __index: 
       `rawset(self, key, value(key)`]] 
     end 
    }) 
end 

local tab = indirect_table() 

tab.foo = function (key) return key .. 'bar' end 

print(tab.foo) --> 'foobar' 

Примечание: в этом примере используется замыкание, но вы можете реализовать этот вид рисунка с использованием getmetatable, а также.


Лично я бы абстрактное это в шаблон, который позволяет косвенный произвольные ключи и значения, а их действия быть указаны. Я считаю, что этот тип шаблонов будет в основном использоваться программно, а не вручную, где результаты ключевых значений зависят от полученных входов. Опять же, не красивая, но немного более надежная (необязательные действия).

local function I (_, value) return value end 

local K = setmetatable({ 
    __call = function (actor, key) 
     return actor.action(key, actor.value) 
    end 
}, { 
    __call = function (K, value, action) 
     return setmetatable({ value = value, action = action or I }, K) 
    end 
}) 

local T = setmetatable({ 
    __newindex = function (self, key, value) 
     if getmetatable(value) == K then 
      value = value(key) 
     end 

     rawset(self, key, value) 
    end 
}, { 
    __call = function (T, o) 
     return setmetatable(o or {}, T) 
    end 
}) 

Простое использование:

local function concat (left, right) return left .. right end 

local t = T {} 

t.foo = K('bar', concat) -- with a common action 
t.zar = K({}, unknown_action) -- without action (`nil`) 
t.qux = 'qaz' -- standard 

print(t.foo, t.zar, t.qux) 

Это странно метапрограммированием. Я бы дважды проверял рассуждения о необходимости такого подхода. Возможно, вы попадаете в ловушку XY Problem? На самом деле это похоже на решение проблемы, которая не обязательно должна существовать в первую очередь.

+0

Благодарим за то, что нашли время ответить на это подробное решение.Я дал больше контекста моей проблемы и как мне это удалось с предварительной обработкой таблицы, предложенной lhf в комментарии к ее ответу. – psychoslave

 Смежные вопросы

  • Нет связанных вопросов^_^