Перейти к контенту
Malandrinus

Язык Lua. Общие вопросы программирования

Рекомендуемые сообщения

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

Изменено пользователем Kirgudu
Ссылка на комментарий

 Подскажите почему при построении "башни" из таблиц (без явных ключей) в глубину, "срезать" таблицу на определённом уровне можно так: (не забываем про теорию - в луа переменные содержат ссылки на таблицы, а не копии таблиц!)

Скрытый текст

local t = {{{{{}}}}} -- 4 вложенных
local g = t
local tst = t[1][1][1]

print(t[1][1][1][1]) -- table:
t[1][1] = t[1][1][1]
print(t[1][1] ==  tst, t[1][1][1][1] ) -- true, nil срезалась и "хвост" подтянула!
-- А так нельзя
print( t[1][1][1][1] ) -- table:
local a = t[1][1]
local b = t[1][1][1]
a = b
print( t[1][1][1][1] ) -- table: хвост не подтянут!
print( t[1][1] == g[1][1]) -- true
-- и срез не произошёл! Проверим ещ переменные:
print( a == g[1][1], b == g[1][1], a==b) -- false, false, true
print(a == g[1][1][1], b == g[1][1[1]]) -- true, true

print(a == t[1][1][1], b == t[1][1[1]]) -- true, true
print(t==g) -- true

 


Как можно программно реализовать правильный срез таблицы из "башни", если вложенную таблицу на определённом уровне я получаю циклом:

local pred = t
while (pred) do
    pred = pred[1]
   if pred == t[1][1] then
        pred = pred[1] -- не работает так. см 2 пример
   end
end

 

Изменено пользователем Graff46
  • Нравится 1
Ссылка на комментарий
4 часа назад, Graff46 сказал:

a = b print( t[1][1][1][1] ) -- table: хвост не подтянут! print( t[1][1] == g[1][1]) -- true

Сначал ты в a положил t[1][1], потом t[1][1][1]. Почему в t что-то должно было измениться?

Если думать в терминах ссылок, то сначала в а положили ссылку на таблицу второго уровня, потом в а положили ссылку на таблицу 3 уровня. Таблица t при этом никак не модифицировалась.


Подарки

  • Ссылка на комментарий

    @abramcumner Я думал что я в а положил t[1][1] , потом t[1][1] приравнял к t[1][1][1], но это работает не так. Вот тут товарищ расписал, нужно было всего лишь таблицу уровнем ниже взять и к а приписать индекс.

    Ссылка на комментарий

    Часто бывают ситуации когда можно приравнять какой-то объект к функции и эта ф-ция будет вызываться при определенных условиях и параметрах, но часто этого мало - хочется несколько ф-ций повесить на 1 объект. Для этой цели я написал 2 реализации. Собственно хочется узнать какой способ более приемлем,  я делал тест на множественное выполнение 4 функций (2^20 раз) - по времени результат приблизительно равный.

    Скрытый текст

    Ф-ции записываются в таблицы, а таблицы одна в другую, у каждой таблицы в метатаблице указано, что при вызове оной выполнится ф-ция и вложенная таблица и так по цепочке:

    
    local noop = function() end
    
    local storage = {noop}
    setmetatable(storage, {__call = function(slf, ...) return slf[1](...) end})
    local b = storage
    
    function add(f) -- добавить ф-цию в линию выполнения
        local texe = {noop, f}
        setmetatable(texe, {__call = function(self, ...)
            self[2](...); 
            return self[1](...)
        end})
        b[1] = texe
        b = texe
    end
    
    function find(f_obj) -- поиск ф-ции из линии, если нашлась - возвращает её родительскую таблицу (сама найденная ф-ция 2 элемент в таблице)
        local stack, prevStack = storage, storage
        while (type(stack) == "table") do 
            stack = stack[1] 
            if stack[2] == f_obj then
                return prevStack
            end
            prevStack = stack
        end
    end -- не громоздкий поиск ф-ции в линии
    
    function del(fun) -- удаление ф-ции из линии
        local a = find(fun)
        a[1] = a[1][1] 
    end

     

    2-й способ:

    Скрытый текст
    
    local line = {test, test2, test3, test4}
        
    local function iniciator(...)
        for i=1, #line do
            line[i](...)
        end
    end
    
    setmetatable(line, {__call = function(slf, ...) return iniciator(...) end})

    Специальных ф-ций для получения и удаления ф-ций из таблицы не писал, подразумеваю, что пользователь сам умеет работать с простыми таблицами.

    Первый способ содержит больше метатаблиц, подключенные ф-ции оборачиваются в талицу со своей метатаблицей и вызовом подключенной ф-ции, вызовом вложенной таблицы. Все хитро и не просто на первый взгляд. Второй способ проще, но там цикл с обходом. Интересно мнение и предложения знающих людей.

    Изменено пользователем Graff46
    Ошибки исправлял
    Ссылка на комментарий

    Привет.

    Ребяты, помогите с шаблоном для удаления комментариев из xml.

    Пробовал так:

    <!%-%-.+%-%->

    Но захватывается всё, начиная с первого и по последний комментарий. Ну, это ожидаемо. А так

    <!%-%-.-%-%->

    Вообще ничего не захватывает, хотя, по идее, должно...

     

    upd: вопрос снят, очепятка была :blush:

    Изменено пользователем naxac

    Аддон для ОП-2.09.2: Яндекс/Google/GitHub

    naxac.gif


    Подарки

    Ссылка на комментарий

    @naxac, использовал бы длл для хмл в луа или скрипт-модуль готовый xml.lua

    Изменено пользователем Graff46
    Ссылка на комментарий

    @Graff46, мне своё нравится делать, пусть даже это будет велосипед, который уже тысячу раз изобрели.

    Изменено пользователем naxac
    • Нравится 2

    Аддон для ОП-2.09.2: Яндекс/Google/GitHub

    naxac.gif


    Подарки

    Ссылка на комментарий

    Здрасьте.

     

    Задача: вызвать несколько функций при чтении нетпакета, составляя их названия из строки "r_" и типа переменной. На выходе должно получиться r_u8(), r_stringZ(), r_float() и т. д. Шаблон, насколько мне известно, такой: namespace["func"](arg1, arg2). Пример вызова функции без привязки к объекту: _G["time" .. "_global"]().

    Тест:

    net_packet["r_u32"]() – вылет "pure virtual function call" (ожидаемо – нет ссылки на нетпакет)
    • pk:net_packet["r_u32"]() – вылет "attempt to index global 'script_filename' (a nil value)"

     

    Каким должен быть синтаксис при таком вызове функций?

    Мини-моды: ТЧ ЧН ЗП

    Шпаргалка

    Ссылка на комментарий

    @Norman Eisenherz

    pk = net_packet()
    
    -- Если функция без аргументов
    pk["имя_функции"](pk)
    
    -- Если функция с аргументами a, b, c
    pk["имя_функции"](pk, a, b, c)

     

    • Нравится 1

    S.T.A.L.K.E.R. CoP Objects (upd 10.04.24)


    Подарки

  • Ссылка на комментарий

    Не уверен я, куда этот вопрос писать, но попробую сюда.

    Вопрос про объявление и наследование классов в Lua, c Luabind-ом из OGSR.


     

    Скрытый текст

     

    Код примерно такой структурно

    
    class "A"
    function A:__init()
    end
    function A:__finalize()
    end
    ***
    class "B" (A)
    
    function B:__init (...) super()
    	self.params = {...}
    end
    ***
    class "C" (B)
    
    function C:__init (...) super(...)
    end
    ***
    class "D" (C)
    
    function D:__init (...) super(...)
    end
    ***
    class "E" (D)
    
    function E:__init (...) super(...)
    end
    ***
    class "F" (E)
    
    function F:__init (...) super(...)
    end
    *** // и т.д.
    function Create()
    same_object = G_script.G(...)
    end
    -- Где '***' - обозначают разные файлы...

    Возвращает примерно такой лог

    
    [19.11.20 15:41:07.174] expected class [B] to derive from or a newline
    [19.11.20 15:41:07.181] ***************************[ScriptCrashHandler]**********************************
    [19.11.20 15:41:07.181] stack traceback:
    	[C]: at 0x018000bee4
    	....a.l.k.e.r_ogsr\gamedata\scripts\script_B.script:20: in main chunk
    	[C]: in function '__index'
    	....e.r_ogsr\gamedata\scripts\script_C.script:15: in main chunk
    	[C]: in function '__index'
    	...a.l.k.e.r_ogsr\gamedata\scripts\script_D.script:15: in main chunk
    	[C]: in function '__index'
    	....a.l.k.e.r_ogsr\gamedata\scripts\script_E.script:15: in main chunk
    	[C]: in function '__index'
    	...a.l.k.e.r_ogsr\gamedata\scripts\script_F.script:15: in main chunk
    	[C]: in function '__index'
    	....a.l.k.e.r_ogsr\gamedata\scripts\script_G.script:15: in main chunk
    	[C]: in function '__index'
    	....t.a.l.k.e.r_ogsr\gamedata\scripts\subtask.script:270: in function 'Create'

    Где строка "expected class [ Х ] ... " неизменно указывает на тот класс, который является потомком класса, не имеющего родителей.

    Т.е. если например я C наследую от A - ругаться лог будет на C.

    Если же С наследует от B, B наследует от A, а для A я создам новый класс-родитель X. Так что А наследует от X, а X ни от кого - то ругаться будет на A.

    Разве я не могу наследовать от скриптовых классов?

    Если сам по себе скриптовый класс (т.е. просто вот это:)

    
    class "same"
    function same:__init()
    ...
    end
    function same:method0()
    ...
    end
    , etc...

    Исправно работает.

    Конструкции вроде биндеров

    
    class "actor_binder" (object_binder)
    function actor_binder:__init (obj) super(obj)
    ...

    Тоже работают, наследуя от классов, объявленных в движке. object_binder в данном случае.

    А от скриптового наследовать нельзя?

     

    * * *

     

    По-копавшись, обнаружил искомое в старом m_netpk.script, артосо-модуль т.е.

    Там объявлен class "net_base" - не наследующий ни от кого, и от него наследуются другие классы. Т.е. там это работало, хотя модуль не под OGSR создавался.

    А тут? Что я делаю не так, или что надо делать не так, объявляя наследование классов друг от друга в скриптах под OGSR. Проясните, кто в курсе.

     

     

    Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

    Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

    AMD Ryzen 9 7950X (16 ядер, 5.7ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

    Ссылка на комментарий

    Здрасьте.

     

    Если this["подстановка"]() позволяет вызвать функцию по строковому имени из текущего скрипта, то для чего нужны конструкции вида this.точное_имя(), если прямой вызов по имени функции и так действует в текущем скрипте?

     

    Примеры:

    ЗП [utils.script] this.vector_copy_by_val()

    ТЧ [uilts.script] и [xr_talker.script] this.vector_copy_by_val() – две разные функции, но каждая вызывается только в своем скрипте

    Мини-моды: ТЧ ЧН ЗП

    Шпаргалка

    Ссылка на комментарий

    Если ты спрашиваешь, то тебе это сейчас точно не нужно. Когда и если понадобится, ты сразу поймёшь. Мне пару раз нужно было. Если я правильно помню, у меня в скрипте была функция с таким же именем, как и в _g.script, но с другим содержимым конечно. Вот для её вызоваа я и использовал вариант через this. Это если я ничего не перепутал за давностью. Кажется ещё какие-то заморочки были, но я уже не помню. 

    • Нравится 1
    Ссылка на комментарий

    IDE: ZeroBraine. Lua 5.3

    Решил написать ф-цию рандомной выборки из таблицы без повторений на каждом проходе по таблице. В 1 случае я теряю переменную (то ли аргумент, то ли вложенную ф-цию), но если я теряю переменную, то должны быть ошибка или nil. но у меня ф-ция начинает выдавать значения из 2х переменных.

    Вариант с ошибкой:

    Скрытый текст
    
    
    math.randomseed(os.time())
    function foo (t, desc)
    	local itera = 0
    	local skip = {}
    
    		function bar ()
    			local val = math.random(1, #t)
    			if itera == #t then
    				skip = {}; 
    				itera = 0
    			end
    			if skip[val] then
    				return bar()
    			else
    				skip[val] = true
    				itera = itera + 1
    				print(desc..':', t[val])
    			end
    		end
    		return bar
    end
    
    local t1 = {'red', 'blue', 'green', 'white', 'yellow'}
    local t2 = {'apple', 'orange', 'cherry', 'potatoes', 'tomato'}
    local c1 = foo(t1, 'color')
    local c2 = foo(t2, 'fruits')
    
    for i = 1, 20 do
    	c1()
    	if i % 5 == 0 then 
    		print('------------------')
    	end
    end

     

    его вывод:

    Скрытый текст

    Программа запускается как '"E:\1\lua\ZeroBraneStudio\bin\lua53.exe" -e "io.stdout:setvbuf('no')" "E:\1\lua\ZeroBraneStudio\my\test1.lua"'.
    Программа 'lua53.exe' запущена в 'E:\1\lua\ZeroBraneStudio\my' (pid: 1816).
    color:    blue
    color:    white
    color:    yellow
    fruits:    apple
    color:    red
    ------------------
    fruits:    cherry
    fruits:    potatoes
    fruits:    tomato
    fruits:    orange
    fruits:    cherry
    ------------------
    color:    green
    color:    white
    color:    blue
    color:    red
    fruits:    orange
    ------------------
    fruits:    apple
    color:    green
    fruits:    tomato
    color:    yellow
    color:    white
    ------------------
    Программа завершена за 0.05 секунд (pid: 1816).

    Исправленный вариант:

    Скрытый текст
    
    
    math.randomseed(os.time())
    function foo (t, desc)
    	local itera = 0
    	local skip = {}
    	return function ()
    		function bar ()
    			local val = math.random(1, #t)
    			if itera == #t then
    				skip = {}; 
    				itera = 0
    			end
    			if skip[val] then
    				return bar()
    			else
    				skip[val] = true
    				itera = itera + 1
    				print(desc..':', t[val])
    			end
    		end
    		return bar()
    	end
    end
    
    local t1 = {'red', 'blue', 'green', 'white', 'yellow'}
    local t2 = {'apple', 'orange', 'cherry', 'potatoes', 'tomato'}
    local c1 = foo(t1, 'color')
    local c2 = foo(t2, 'fruits')
    
    for i = 1, 20 do
    	c1()
    	if i % 5 == 0 then 
    		print('------------------')
    	end
    end

     

    Вывод:

    Скрытый текст

    Программа запускается как '"E:\1\lua\ZeroBraneStudio\bin\lua53.exe" -e "io.stdout:setvbuf('no')" "E:\1\lua\ZeroBraneStudio\my\test1.lua"'.
    Программа 'lua53.exe' запущена в 'E:\1\lua\ZeroBraneStudio\my' (pid: 7496).
    color:    yellow
    color:    blue
    color:    red
    color:    white
    color:    green
    ------------------
    color:    yellow
    color:    white
    color:    green
    color:    blue
    color:    red
    ------------------
    color:    green
    color:    yellow
    color:    blue
    color:    red
    color:    white
    ------------------
    color:    yellow
    color:    white
    color:    blue
    color:    red
    color:    green
    ------------------
    Программа завершена за 0.05 секунд (pid: 7496).

    Я понимаю, что где то потерял переменные, но где и как? В 1м случае в вывод попали значения из 2-х таблиц, если вызов ф-ции был для одной таблицы?

    Изменено пользователем Graff46
    Ссылка на комментарий

    @Graff46, крутой код, ничего не скажешь...

    1. А зачем в функции bar() рекурсия? Почему не использовать repeat-until? Представь стек вызовов если в таблице t будет 1000 значений.

    2. Обязательно хранить в c1 и c2 замыкание bar() со всеми переменными? Особенно с параметром t, в котором может быть большая таблица. Лучше пересмотреть реализацию в сторону более "простого" кода.

     

    Откровенно говоря - не знаю где проблема. Возможно в том, что в первом примере функция bar() именованная.

    S.T.A.L.K.E.R. CoP Objects (upd 10.04.24)


    Подарки

  • Ссылка на комментарий

    Здрасьте.

     

    Задача: показать разницу в работе модификаторов поиска * + - ?. Один пример удалось подобрать так, чтобы результат поиска отличался для всех вариантов, но хочется чего-то более наглядного. Может, кому попадалось более интересное сочетание строки и шаблона?

    Spoiler
    local str = "aa1a22a333"
    local t = {}
    for x in str:gmatch("a%d#") do
    	t[#t +1] = x
    end
    
    #
    *	a, a1, a22, a333		-- буква и 0+ цифр
    +	a1, a22, a333			-- буква и 1+ цифра
    -	a, a, a, a			-- буква и 0+ цифр, короткое совп.
    ?	a, a1, a2, a3			-- буква и 0/1 цифра

     

     

    Мини-моды: ТЧ ЧН ЗП

    Шпаргалка

    Ссылка на комментарий

    Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

    Комментарии могут оставлять только зарегистрированные пользователи

    Создать аккаунт

    Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

    Зарегистрировать новый аккаунт

    Войти

    Есть аккаунт? Войти.

    Войти
    • Недавно просматривали   0 пользователей

      Ни один зарегистрированный пользователь не просматривает эту страницу.

    AMK-Team.ru

    ×
    ×
    • Создать...