Dennis_Chikin 3663 Опубликовано 2 Января 2012 (изменено) Artos, оффтопить, так офтопить... Вот поддержу всеми конечностями. Когда скрипты той же НС всего-лишь после поверхностного касания худеют на четверть - это пол беды. Даже месиво из того, что вчера разбирали (и даже если половина не работает) - тоже еще на так страшно по сравнению с гораздо худшим. Во-первых, оно совмещалось вообще не думая. Например, могут быть подряд несколько попыток удалить один и тот же объект, разумеется, без проверки на его существование. Ну, заспавнено аддоном xStream аптечка, ну удаляется она по уходу непися в офлайн. Ну, нормально. Но так там еще 3 штуки таких, которые тоже удаляют. Причем существование аптечки запомнено еще при netspawn. Ага. Вот так вот прямо в виде серверного объекта... Результат понятен. Ну а что происходит потом с оффлайн_алайфом... В который тоже кусков понапихали. Этот и сам один и тот же предмет в цикле может пытаться удалять. И ведь что-то поправить - надо перелопатить 2 десятка скриптов. А потом перекомпилируется олспавн, и снова лопатим скрипты, вбивая в них руками изменившиеся координаты и номера... Тоже по 2-м десяткам. НУ и бесконечные простыни if ... elseif .... end'а не видно... Бесконечные сканирования for i = 1, 65535 do obj = level.object_by_id(i) ... по нескольку штук в одном апдейте. iterate_inventory() туда-же... Что до ООП и lua, то в данном конкретном случае вызовы вида obj:method() получились весьма неторопливыми, скажем так. И стремление все-все построить в виде якобы объектов оказывается крайне неполезным, если сравнить с результатом разворачивания этого творчества в самые обыкновенные функции. Upd: просто некоторые инструменты могут быть опасны. Особенно, используемые по принципу "а по тому, что все так делают". К ООП это вполне относится. Изменено 2 Января 2012 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 16 Января 2012 Вот интересно, почему local sim = alife() и далее по тексту - можно писать, а с vector() такое не прокатывает ? Универсальное правило есть какое-то ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 14 Мая 2012 Ну, давайте еще раз поговорим об этом. В смысле, о таблицах и добавлении/удалении записей в них. Это я ведусь на провокацию. На самом деле говорили уже много где неоднократно, разработали теории, использовали много страшных слов типа "индекс" и "хеш", однако лично мне симпатичнее всего давний вывод malandrinus'a, что нефиг возиться с тем, что ведет себя явно негуманно, и если таблицу можно пересоздать - лучше тупо пересоздать. Вообще говоря, ни кто не обещал какого-либо доступа к внтреннему счетчику, использующемуся при присваивании вида t = { v1, v2, ... }. Обещали только, что будет работать пара table.insert()/table.remove() и доступ вида v = t[n]. Тем не менее, когда операция t[n] = v делает внутри таблицы нечто непредсказуемое, а затем table.remove( t, n ) игнорирует наличие в таблице записи с индексом n, и удаляет фактически что попало - это вряд-ли можно считать как-то соотвествующим принципам гуманизма. P.S. А вызов функций и передача параметров ( не говоря уже о вызове методов у "самодельных" объектов ) в текущей имплементации таки явно относятся к "тяжелым" операциям. Был бы оптимизатор, как практически во всех современных плюсях - разговор был бы совсем другой. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 14 Мая 2012 (изменено) "Обрывок кода" - это и есть весь сколько-нибудь значимый код. nil в таблицу здесь попасть не может, нецифровых индексов или "дырок" случиться тоже не может. В смысле, была надежда, что table.remove при однократном вызове таки индексы исправит как надо. И говорить здесь имеет смысл именно про гуманизм. По той причине, что если у нас в результате получилась хэш-таблица, хочется ожидать, что # вернет 0 (ну или сколько у нас там осталось от индексированного, а table.remove() просто не будет делать с ней ничего. Иначе лучше ими действительно не пользоваться. В действительности же предложенное решение с t1000s = #t1000 не спасает, поскольку до момента, когда крах таблицы становится очевидным (нет записи, которая должна быть, есть та, которой быть не должно), # возвращает ровно то же самое, что и посчитано руками. И даже хуже того, если считая руками, мы получим вылет по попытке что-то делать с уже несуществующим элементом, то с использованием # - не узнаем даже о самом факте краха. Собственно, пару лет назад так и случилось, когда под девизом "заоптимизируем все" поменяли на автомате все табличные функции на доступ через #t+1 / #t - 1. Про вариант трогать таблицу в цикле, и присваивать nil произвольному элементу - это-то давно обсудили, и все согласились (а по существу спорить не с чем), возможности же, скажем, изменить произвольный существующий элемент таблицы, без удаления/добавления - весьма и весьма жаль. Ну и для "солянок" очевидно то, что "непредвиденное" с любой нелокальной таблицей скорее произойдет, чем не произойдет. А в свете того, что удаление одиночного элемента - операция крайне редкая, таблицы же по большей части не великих размеров - я вот для себя вижу скорее причину отказаться именно от использования table.remove(), чем от чего-либо еще, и таблицы по необходимости пересоздавать. Тем более, что многие и сами по себе живут не долго. P.S. Да, видимо, формулировка про "делает непредсказуемое" внесла неоднозначность. Читать следует как "внутри таблицы происходит нечто непредсказуемое при". Изменено 14 Мая 2012 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 14 Мая 2012 (изменено) Продолжаем разговор про таблицы. Вот код: function test_tbl() local t, s = {}, 0 for i = 1, 10 do t[i] = i end table.remove( t, 10 ) t[10] = 10 table.remove( t, 10 ) _util["list_tbl"]( t, "test_tbl" ) end (list_tbl - там много всякого, но, в общем, классическое for k,v in pairs(t) do ... end) Вот конечный результат: 1, value: 1 .... 8, value: 8 10, value: 10 9 records in table [test_tbl] ( # возвращает 8, что логично. ) Промежуточные - 10(10), 9(9), 10(10) То есть, либо table.insert()/table.remove() - кстати, in pairs()/next() не гарантируют последовательности 1, 2 ... - либо - все остальное. Artos, по поводу того, что в соли "очень много" всего - я бы даже жесче сказал. Приводим в порядок потихоньку. Upd: да нет, я уже не сетую. Просто чтобы исключить другие причины. И, да, вот конкретно такой результат - он, все-таки, несколько удивляет. Скажем, я бы понял вылет с грохотом, или 1,2...9,10 (то есть, несработавшее вообще удаление). Gun12, в смысле, код попробован на чистом lua, и конечный результат: 1, 2, ... 8, 9 ? Upd2: проверил на меньших значениях: в сталкерском lua то же самое - рушится. Со SciTE, похоже, действительно, разница в реализациях. Ну и аминь. В принципе, имеет право - отрицать глупо, бессмысленно, и ничего не изменит. Изменено 14 Мая 2012 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 14 Мая 2012 (изменено) Artos, см. выше апдейт 2: 10 или не 10 - не влияет. Да хоть 3 всего. А вот для случая с одной - двумя записями - сейчас тоже проверю. Уже интересно стало. Gun12, там в начале разговора было резюме: исходя из описания lua - не от ПЫС, а от создателей собственно языка, сталкеровкий lua на такую камасутру право, увы, имеет. (Хотя это, конечно, ближе к буквоедству - "делаем так, по тому, что явно не запрещено", чем к рациональному.) Изменено 14 Мая 2012 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 24 Сентября 2012 А подскажите кто-нибудь менее монстрообразную конструкцию для замены: v1, v2, v3, v4 = s:match"(%-?[%-%d%.]*)[%s%,]*(%-?[%-%d%.]*)[%s%,]*(%-?[%-%d%.]*)[%s%,]*([%d%.]*)" И, кстати, я, похоже, что-то не понимаю с поведением конструкций вида string.gfind( s, "[%w]*] ) и string.gfind( s, "[%w]+] ) Как оно должно работать ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 24 Сентября 2012 По первому вопросу я хочу 4 числа без мусора из строки типа " -195.01,-5.12, 146.45, 50чего-то там ". Все другие варианты, которые смог придумать, дают странное. Чисел всегда 4 (ну или вообще 2), и именно по этой причине с итератором городить огород не хочется. По второму вопросу: ну, там union, да. Для случая с просто %w смысла особого нет, но поведение всей конструкции от этого изменяться же не должно по сравнению со, скажем %w_ или %w%s ? Или должно ? Если символ в строке не попал под шаблон, а мы просим 0 или больше - будет ведь все равно пустая строка ? А если не менее одного - nil ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 24 Сентября 2012 Дальше, зачем включать в символьный класс ещё и знак минуса "%-"? Остался от экспериментов. В общем, переписал пока так: (%-?[%d%.]+)%,%s* n раз без хвоста Вроде работает, и даже ошибку в данных отловил, которая раньше, с итератором и пачкой адских преобразований проскакивала. Знак "*" по-любому делает возможным нахождение пустой строки в произвольном месте. Я кстати не уверен, что Lua это обрабатывает корректно. Ага, похоже на то, что итератору крышу сносит. Причем вместо пустых строк начинает выдавать первое вхождение. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 3 Декабря 2012 (изменено) Наверное, сюда все-таки. Ибо торможу. Не понимаю, КАК этот код работает в соответствии с комментариями. У меня наоборот получается. level_weathers.script: local function is_time_between(t, t1, t2) -- returns true if t1 <= t <= t2 assuming 24 hour clock return (t1 < t2 and (t >= t1 and t <= t2)) or (t1 > t2 and (t >= t1 or t <= t2)) end function WeatherManager:update_times(last_idx) -- update the sliding time window indexes self.last_time_idx = last_idx self.next_time_idx = last_idx % #self.trans_times + 1 self.last_time = self.trans_times[self.last_time_idx] self.next_time = self.trans_times[self.next_time_idx] end -- adjust time indexes so that current time is within the window that is defined by these indexes function WeatherManager:fix_times() self.next_time_idx = 1 repeat self:update_times(self.next_time_idx) until is_time_between(self.time, self.last_time, self.next_time) end То есть, repeat ... until должно выполняться ПОКА время в заданном интервале. Или нет ? Снимите меня кто-нибудь с ручника. И, кстати, код производит впечатление сильно небезопасного, почему-то. malandrinus, ага, спасибо. Это я просто странного прочитал, оказывается. А паскаль - он как-то мимо меня пролетел весь. Мда, погодку по-хорошему надо делать или полудинамической (переход ночью между однотипными конфигами вместо той жуткой простыни почасовой (и половина - криво), или динамической совсем (генерить вообще все). Тогда туда можно будет всякого вкусного подцепить. Изменено 3 Декабря 2012 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 11 Декабря 2012 По поводу оператора # по его поведению и скудному описанию языка можно предположить, что он возвращает значение некоего счетчика. А вот как и когда создается значение этого самого счетчика - очень похоже, что при первом требовании. То есть, первом применении собственно # или table.что-то-там() Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 23 Декабря 2012 Как и ты заметил, в игре именно вызов без аргументов (=> результат с плавающей запятой) более быстрый (проверял не раз тестами на практике), чем с заданными целочисленными аргументами. Т.е. вероятно в движке компиллятор Lua все же именно math.random() исходен, а все остальное пляшет от него, приводя к накладным расходам. Я как-то мерял время на function f() return end ... function f( a1, a2, ... an ), ну и соответственно давая на вход разное количество аргументов. Задумчивость по мере увеличения количества аргументов растет очень сильно. Аналогично и с возвращаемыми. ( Вызов метода у объекта - еще дороже - в разы. Видимо, в т.ч. из-за передачи/обращения к ссылки на сам объект. ) В общем, функции в несколько строк делать не надо однозначно - лучше уж "китайский код". Возможно, не лишено смысла более интенсивное использование переменных с областью видимости на весь модуль. Ну и, да, плавучка у ЛУА более "нативная", чем целочисленка. P.S. Вот чего не понимаю, так это то, что обращение к переменным, записанное как v["id"] чуть не в разы быстрее, чем v.id. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 23 Декабря 2012 Во-первых, все же топик по языку Lua, а не по его интерпретации в Сталкере, поэтому в постах о тестировании следует обязательно указывать о "в чистом Lua" или в игре... Во-вторых, не нужно выпячивать субъективные оценки без сравнительных критериев или пояснений. Да, виноват. Это я про SoC. "Очень сильно" - это значит - сравнимо или даже больше, чем несколько-десяток строк с арифметикой/логикой, не оформленных в отдельную функцию. Ну, то есть, вынеся это в функцию - получаем выполнение в разы дольше. Вызывая не как f(), а как myobj:f() - опять же в разы. Ну или как приведенный в тексте пример с function f() return end vs. function f( a1, a2, ... an ) return end - логично было бы ожидать разницу во времени на каждую переменную все-таки меньше, чем на собственно вызов. Когда счет идет на миллисекунды (а именно на них и идет), то для 20-50 ms апдейта или вызова "пачкой" десятка-другого апдейтов - это критично. Скажем, я отказался от использования в 50 ms цикле актора чего-либо кроме "биорадара"/детектора артов. Не успевает. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 5 Января 2013 Это здесь обсуждалось какое-то время назад. lua SoC вычисляет пользовательский размер таблицы при первом обращении, требующем этот самый размер. То есть, до оператора # или table.remove() его просто не существует (есть некие внутренние счетчики, на которые тонко намекает стандарт, и которые пользователю недоступны в принципе). Размер вычисляется неизвестно как, но от 1 до t[n] ~= nil с шагом 1. Повторно НЕ пересчитывается. table.insert()/table.remove() изменяют его сами как им заблагорассудится. Кстати, при попытке применить table.remove() к несуществующему с точки зрения всех этих счетчиков и размеров элементу (даже если он на самом деле есть) приводит к странному (что тоже вполне разрешено стандартом) Другие lua могут вести себя иначе (стандартом разрешено). Резюме: либо все делать руками ( if t[k] == nil then n = n + 1 end ; t[k] = v и if t[k] ~= nil then n = n - 1 end; t[k] = nil ), либо только table.insert( t, v ) и if n <= #t then table.remove( t, n ) end. Инициализация в этом последнем случае допустима как t = { 1, 2, 3 } но недопустима как t = { [1] = 1, [3] = 3 } С обращением в цикле, соответственно, будут особенности. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 24 Февраля 2013 Интересно, насколько неправильно я понимаю, что имея функцию вида function inc_a( a ) return a+1 end обращаться к ней как this.inc_a( a ) - бессмысленно чуть более, чем полностью ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 24 Февраля 2013 (изменено) :не совсем понятно, о чём именно вопрос. Именно к такой функции бессмысленно? Да, именно такой. Или реальный пример:dialogs.script: function is_wounded(first_speaker, second_speaker) if db.storage[first_speaker:id()].wounded ~= nil and db.storage[first_speaker:id()].wounded.wound_manager.can_use_medkit == true then return false end return xr_wounded.is_wounded(first_speaker) end function is_not_wounded(first_speaker, second_speaker) return not this.is_wounded(first_speaker, second_speaker) end На правильное использование похоже вотэто: class "motivator_binder" ( object_binder ) ... :bind_object(this.motivator_binder(npc)) для отвязки от необходимости явно указывать имя модуля, в котором расположен код таймера.В смысле ? global name space ? функция в одном модуле, зовем из другого ? Изменено 24 Февраля 2013 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 19 Марта 2013 Что-то я слегка не понял эту конструrцию: if sDiv then sPattern = '[^%s%'..sDiv..']+' .. for sValue in sStr:gmatch(sPattern) do table.insert(tRet, sValue) endЕсли sDiv есть, то ЧТО у нас будет в таблице ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 19 Марта 2013 (изменено) Смысл сего действа неясен. То есть, при sDiv == "," и строке ",,,,,,,,,," - получаем таблицу с 10 запятыми ? А из строки 12345,6789 получим таблицу с "12345," и "6789" ? Да, иначе там else pattern = "[_%w]+" - это как раз понятно. И вот еще тоже из той же серии. Здесь у меня вообще фантазия отказывает: for k, v in string_gfind( s, "(.*)" ) do t[k] = v end А это что должно делать ? Изменено 19 Марта 2013 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 19 Марта 2013 Artos, приведенное - это amk ? Ну, как бы, я бы не стал задавать вопрос про закомментированный кусок. Очевидно, он был кем-то раскомментирован. Или взят откуда-то еще до того, как был закомменчен. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение
Dennis_Chikin 3663 Опубликовано 20 Марта 2013 При чтении ltx white_spaces любого вида по-моему вообще игнорируются. SOC по крайней мере. Сколько чего в лог не выводил - всегда идет что-то типа v1,v2,v3. И есть шанс, что для %s пробел и табуляция тоже идентичны. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Поделиться этим сообщением Ссылка на сообщение