setmetatable

Страницы: 1
RSS
setmetatable
 
Код
function func(v)
  return v * v
end

s = {
  f = function(v)
    local r = s.r
    if not r then
      r = func(v)
      s.r = r
    end
    return r
  end
}

print(tostring(s.f(3)))
print(tostring(s.f(3)))

Функция s.f() запоминает вычисленное значение и при повторном обращении возвращает раннее вычисленное значение.
Можно ли описать её через setmetatable?
PS: возвращать она должна раннее сохранённое значение, независимо от переданного аргумента при повторном вызове.
 
Цитата
Старатель написал:
Код
   function   func (v)
   return  v  *  v
 end 

s  =  {
  f  =   function (v)
     local  r  =  s.r
     if   not  r  then 
      r  =  func(v)
      s.r  =  r
     end 
     return  r
   end 
}

 print (tostring( s.f ( 3 )))
 print (tostring( s.f ( 3 )))  

Функция s.f() запоминает вычисленное значение и при повторном обращении возвращает раннее вычисленное значение.
Можно ли описать её через setmetatable?
PS: возвращать она должна раннее сохранённое значение, независимо от переданного аргумента при повторном вызове.
setmetatable из числого луа можно использовать для таблиц (хаки не принимаем во внимание). К функциям setmatatable не стоит применять.
 
s = setmetatable( {},   function(t,i)
                                  local result = (считаем что-то)
                                  t[i] = result
                                  return result
                                end)



теперь расчет каждого поля таблицы s будет проходить единожды.

Как я понимаю, вам потребовалось что-то типа этого
 
Цитата
s_mike@rambler.ru написал:
s = setmetatable( {},   function(t,i)
                                  local result = (считаем что-то)
                                  t[i] = result
                                  return result
                                end)
Цитата
bad argument #2 to 'setmetatable' (nil or table expected)

Но я понял, что для моей задачи (кэширование только одного элемента таблицы) первый вариант будет лучше.
 
Цитата
Старатель написал:
Цитата
s_mike@rambler.ru   написал:
s = setmetatable( {},   function(t,i)
                                  local result = (считаем что-то)
                                  t = result
                                  return result
                                end)
Цитата
bad argument #2 to 'setmetatable' (nil or table expected)
Но я понял, что для моей задачи (кэширование только одного элемента таблицы)  первый  вариант будет лучше.
я прошу прощения. Конечно должно быть так:

s = setmetatable({}, { __index = function(t,i) local result = (считаем что-то)
t = result
return result
end})
 
А как это использовать? У меня не кэширует:
Код
s = setmetatable({}, { __index = function(t, i)
  local result = print('Считаем...') or i * i
  t = result 
  return result 
end})
print(tostring(s[3]))
print(tostring(s[3]))

Результат:
Цитата
Считаем...
9
Считаем...
9
 
Цитата
Старатель написал:
А как это использовать? У меня не кэширует:
Код
  s  =  setmetatable({}, { __index  =   function (t, i)
   local  result  =   print ( 'Считаем...' )  or  i  *  i
  t  =  result 
   return  result 
 end })
 print (tostring(s[ 3 ]))
 print (tostring(s[ 3 ]))  

Результат:
Цитата
Считаем...
9
Считаем...
9
старатель. При копировании текста из одного сообщения в другое чудесный форум превратил t[i] просто в t.

невозможно общаться. Как в арке такую халтуру приняли в виде сайта...

позвоните мне скайпом mikemsk - проще словами, чем здесь мучиться.
 
Понял, спасибо!

Код
s = setmetatable({}, {__index = function(t, i)
  local result = i * i
  t[i] = result 
  return result 
end})
 
Код
local t = {vol = 0}
table.insert(t, 1, 3)  -->  t.vol = 3
table.insert(t, 2, 2)  -->  t.vol = 5
table.insert(t, 3, 5)  -->  t.vol = 10
table.remove(t, 2)     -->  t.vol = 8

Можно сделать через метатаблицу, чтобы при добавлении/удалении элемента в таблице в vol автоматически изменялась сумма всех индексных элементов?
 
При добавлении в таблицу сделал:
Код
t = setmetatable({vol = 0}, {__newindex = function(self, key, value)
  self.vol = self.vol + value
end})
t[1] = 3
t[2] = 2
t[3] = 5
print(t.vol)  --> 10
Но не нашёл метаметода при удалении элемента.
 
Можно убрать из вашей таблицы поле vol вообще и пересчитывать итоги каждый раз при попытке извлечь значение по ключ vol,  которое пусто.  Для этого есть мета метод __index.  

накладно это или нет - вам виднее
 
Цитата
s_mike@rambler.ru написал:
пересчитывать итоги каждый раз при попытке извлечь значение по ключ vol
Думаю, будет накладно в общем случае, т.к. надо будет при каждом обращении к vol пробегать по всем элементам таблицы. Хотелось бы более элегантного решения.
 
Код
t = setmetatable({vol = 0,
  ins ert = function(self, pos, value)
    if not value then
      pos, value = #self + 1, pos
    end
    self.vol = self.vol + value
    table.ins ert(self, pos, value)
  end,
  remove = function(self, pos)
    self.vol = self.vol - self[pos]
    table.remove(self, pos)
  end
}, {__newindex = function(self, key, value)
    self.vol = self.vol + val ue
    rawset(self, key, val ue)
  end})
Вроде, работает:
Код
t[1] = 3
t:insert(2, 2)
t:insert(3, 5)
t:remove(2)
Страницы: 1
Читают тему (гостей: 1)
Наверх