🐅🤦‍♂️
эм... почему тогда nil?
Не хватает поля __index в табличке, которая устанавливается как мета. Нет метаметода - нет эффекта
Ameliance
хотя нет, не в книге, а в мануале официальном
🐅🤦‍♂️
в книге увидел, пришла мысль что так можно...
t1 = {1, 2, 3, 4, 5} t2 = {} q = {} print(q[1]) setmetatable(q, t2) print(q[1]) t2.__index = tbl print(q[1]) выведет nil nil 1
Ameliance
t1 = {1, 2, 3, 4, 5} t2 = {} q = {} print(q[1]) setmetatable(q, t2) print(q[1]) t2.__index = tbl print(q[1]) выведет nil nil 1
то что выводит nil я и так увидел из своего кода, вопрос у меня почему... то есть так нельзя в принципе никогда писать? setmetatable(megalamp, lamp)
Ameliance
что происходит если вызвать эту функцию?setmetatable(megalamp, superlamp) можно ли ее как-то перефразировать по другому, то есть что она из себя представляет изнутри?
Igor
setmetable не имеет альтернатив на уровне lua, она добавляет метаметоды из метатаблице к твоей таблице, которую ты передаёшь первым аргументом. Метатаблица - это такая штука, которая может содержать в себе переопределения операторов, к прмеру или ключ индексирования, который будет ссылаться на таблицу, в которой Lua будет искать ключи при обращении к оригинальной таблице, которой назначена метатаблица.
Ameliance
пока просто в моей логике я посылаю 2 таблицы и она одну привязывает к другой в качестве метатаблицы
Igor
local meta = { __mul = function(a, b)return a.val * b end } local mytab = setmetatable({val = 10}, meta) print(mytab * 5) -- вернёт 50
Igor
Это переопределение оператора умножения для таблицы
Igor
Полный список метаметодов есть в документации
Igor
когда ты указываешь в метатаблице ключ __index и даёшь ему значение с ссылкой на саму метатаблицу, ты говоришь интерпрератору, что когда происходит обращение к методу оригианльной таблицы, его нужно искать в метатаблице
Igor
local meta = { test = function(a, b)return a.val * b end } meta.__index = meta local mytab = setmetatable({val = 10}, meta) print(mytab:test(5))
Ivan
Прочитай книгу =) Там все очень подробно рассказывается что такое метатаблицы, зачем они, что можно с ними делать.
Ivan
https://www.ozon.ru/context/detail/id/135559046/
Igor
Почти тоже самое, что в первом варианте, но без переопределния метаметода умножения, создаётся функция test внутри метатаблицы, к которой происходит обращение из основоной таблицы
Igor
Про них как раз лучше почитать, да, а то судя по вопросам вообще нет понимания, что такое метатаблицы и с чем их едят
Igor
Тем, что во втором варианте в метатаблице ссылка будет на другую таблицу и с помощью неё будет индексироваться superlamp
Igor
В обоих случаях индексация происходит через таблицу lamp, но во втором создаётся ещё одна, которая является только метстаблицей и не является индексируемой
Igor
Во втором случае метатаблица может содержать только метаметоды, если проще говорить
Igor
Вам проще прочитать PiL, тогда всё встанет на свои места, там объясняется подробнее
Ameliance
Во втором случае метатаблица может содержать только метаметоды, если проще говорить
я читал несколько мест, но как я понял в некоторых статьях были ошибки (к примеру статья Луа за 60 минут) и я немного запутался😅 теперь пытаюсь понять где...
Ameliance
просто в моем коде если я пишу вариант 1. или 2. не происходит никакой разницы...
Ameliance
я уже запарился😢
Ameliance
https://www.ozon.ru/context/detail/id/135559046/
читал уже, не нашел описания что такое метатаблица
Ivan
глава 13, страница 156 "Метатаблицы и метаметоды"
Ameliance
Метатаблица — это таблица где собраны все возможные операции с значением (переменной, текстом, функцией... а в данном случае с таблицей )? То есть метатаблица это набор (таблица) метаметодов (функций) которые выполняются когда мы хотим что-то сделать со значением? То есть a = 5 b = 10 c = a + b означает c = c.__add(a, b) и в итоге c = a + b выдаст с = 15 А если сделать так setmetatable(с, {__add = function(a, b) return a - b end}) то c = a + b будет с = -5, а d = a + b по прежнему будет d = 10 ?
Ameliance
я так понимаю я уже ближе? Вопрос если здесь написать то «родительскую таблицу цифер» (подскажите где найти), то у меня получится сделать, что + будет вычитать?родительскую таблицу строки
Igor
У чисел нет метатаблиц, getmetstable('вообщечтоугодно') вернёт метатаблицу строки
Snusmumriken
Поправка. То есть a = 5 b = 10 c = a + b означает c = a.__add(a, b) мы складываем a и b, должен вызваться метаметод у a А если у a нет метатаблицы, а у b есть, то вообще будет вызвано c = b.__add(a, b) Но у чисел действительно нет метатаблиц, это бы вызвалось будь a или b таблицей/cdata с метаметодом.
Ameliance
Это так не работает
это я понял, потому и написал «подскажите где найти»... и да, где-то видел в интернете запрос на добавление этой функции, но не был в курсе добавили ли
Snusmumriken
это я понял, потому и написал «подскажите где найти»... и да, где-то видел в интернете запрос на добавление этой функции, но не был в курсе добавили ли
Кароч, наличие метатаблицы само по себе — не определяет где детишки ищут недостающие ключи, детишки ищут ключи только и исключительно по __index своей метатаблицы. Если у метатаблицы есть такое поле — они доискивают. Нет поля — нет доискивания.
Snusmumriken
a = {} b = {} setmetatable(a, b) Ничего не изменилось. a не стало где-то доискивать ключи, потому что у b нет специальных полей. Добавим в b поле __index и a начнёт доискивать по этому полю ключи. Удалим это поле — перестанет. Добавим — начнёт, удалим — перестанет. Добавим в b поле __add с функцией — и a можно будет складывать со всякой фигнёй. Удалим — нельзя будет складывать. Вся суть метатаблиц — в специальных полях. Без полей они бесполезны.
Igor
Я что-то заметил, что почти всем трудно даются метатаблицы.
Ameliance
a = {} b = {} setmetatable(a, b) Ничего не изменилось. a не стало где-то доискивать ключи, потому что у b нет специальных полей. Добавим в b поле __index и a начнёт доискивать по этому полю ключи. Удалим это поле — перестанет. Добавим — начнёт, удалим — перестанет. Добавим в b поле __add с функцией — и a можно будет складывать со всякой фигнёй. Удалим — нельзя будет складывать. Вся суть метатаблиц — в специальных полях. Без полей они бесполезны.
Метатаблица — это таблица где собраны все возможные операции со значением (переменной var, текстом 'string', функцией func() ... а в данном случае с таблицей tab={})? То есть метатаблица это набор (таблица) метаметодов (функций __index, __add) которые выполняются когда мы хотим что-то сделать со значением?
Snusmumriken
Когда мы хотим что-то сделать с таблицей, у которой есть эта метатаблица. Да.
Snusmumriken
Определяются перегрузки операторов и всякая специальная фигня.
Snusmumriken
В целом, метатаблицу можно прицепить к трём типам: к таблицам, к cdata и к строкам. Но строки мы пока отметаем, пусть работают как работают, они и так хороши.
Snusmumriken
Всмысли? Он там и так есть. Натравлен на таблицу string.
Snusmumriken
local a = "qwerty" print( a:sub(3, 3) ) --> "e" Строки — уже с метатаблицей, в которой есть __index.
Arslan
В смысле обращение к символу в строке через оператор []
Snusmumriken
Это бешеный оверхед.
Snusmumriken
Во-первых, это нехило замедляет доступ к обычным методам строки, во-вторых — оверхед. В третьих — это будет обращение к байту а не к символу, если встраивать utf8 с обращением именно к юникод-символу — оно будет ещё медленнее )) Кароч, игра не стоит свеч.
Snusmumriken
А в четвёртых — это изменение поведения стандартной библиотеки. Что является весьма нехорошим делом.
Arslan
А если через __call сделать?
Snusmumriken
Ой-ой ))
Arslan
Он же не используется
Snusmumriken
Гипотетически — конечно можно. Но всё равно не надо. Представь что ты опечатался, и вместо функции послал в качестве какого-нибудь колбека строку. И его начали вызывать со странными аргументами (колбековыми), и всё падает, весьма громко но очень непонятно ))
Igor
Это прям что-то совсем жуткое
Snusmumriken
Когда я был маленький, мне тоже хотелось всё расширять и поливать сиропом синтаксического сахара. А потом я такой увидел, что код превращается во что-то странное, типа: local a = foo"blabla"{bar = 123}"foo""bar" В луа можно так делать. Но не нужно ))
Arslan
Ох ох
Arslan
Это как?
Igor
Я одно время для метатаблицы строк определял __add, чтобы их конкатить, но потом произвёл замеры времени исполнения своего оператора и стандартной конкатенации и что-то перехотел таким заниматься
Snusmumriken
Это как?
Функция foo вызывается со строкой "blabla", и возвращает функцию, которая принимает первым аргументом таблицу, и возвращает функцию, которая принимает строку "foo"..
Arslan
Ухты
Arslan
И даже скобки расставлять не нужно
Snusmumriken
Всё за счёт сахара require"mylib" — если функция принимает одну строку или таблицу, скобки не нужны. А там — просто вызов возвращаемых функций по цепочке.
Snusmumriken
Но разбираться в этом и отлаживать — адовый ад.
Arslan
Я одно время для метатаблицы строк определял __add, чтобы их конкатить, но потом произвёл замеры времени исполнения своего оператора и стандартной конкатенации и что-то перехотел таким заниматься
В php строки соединяются при помощи оператора "."(точка), в начале для это был бред и все время пытался приписать + за что и получал исключения
Arslan
В lua тоже придется привыкать
Snusmumriken
У луа и php, конкатенация и оператор сложения _намеренно_ разделены, чтобы не было как в JS:
Igor
Я одно время с php долго тёрки вёл
Igor
Но это было давно и вообще неправда
Ameliance
что-то из этого является метатаблицей? что-то из этого является частью (то из чего состоит) метатаблица?
Snusmumriken
Это очень интересный вопрос, потому что я вижу только таблицу "tab", и ни одной метатаблицы, только висящие в воздухе имена метатабличных полей и операторы ))
Ameliance
Snusmumriken
Нене, даже не смотри на эту фигню, запутаешься лишний раз.
Snusmumriken
Просто запомни, что в твоём случае — метатаблицы влияют ТОЛЬКО на таблицы. Как дорастёшь до cdata — будешь ещё цеплять их туда.
Ameliance
у чего по умолчанию есть метатаблица?
Snusmumriken
Только строки. У них уже сразу есть метатаблица, но это внутренности языка, тебя это не должно интересовать. Так что считай что ни у чего нет метатаблиц по умолчанию.