Язык Lua. Общие вопросы программирования - Страница 43 - Скрипты / конфиги / движок - AMK Team
Перейти к контенту

Язык 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

А как же, - "В подстроках могут быть вообще любые символы"?

Я уже дал бы ответ, если бы не это уточнение.

Любые - в том смысле, что не обязательно %w.

В каждый момент написания регэкспа мы знаем, каких там точно быть не может.

 

В идеале, если бы (.*)[разделитель1разделитель2разделитель3]*(.*) обрабатывалось бы как единое целое - в смысле, .* - это любые символы, кроме искомого - было бы то, что надо.

@Dennis_Chikin, ну смотри, у тебя "разделители" и "символы строки" - это два взаимоисключающих множества. Любое из них можно определить через другое как [^]. Но по-любому одно из них определить придётся. Выбери то, которое меньше по объёму. Я выбрал явное задание множество символов строки, а разделители задал как обратное ему. Ты говоришь, оно может быть больше. Значит, придётся явно перечислить все символы разделители, а "символы строки" определить, как противоположность "символов разделителей". Либо так либо иначе, но другого пути нет. Изменено пользователем malandrinus
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Что-то я уже совсем ничего не понимаю. Так известны разделители или нет?

Даже если что-то и получиться, то новое выражение .* возвратит одно вхождение, а нужно два.(?)

Тогда придётся gmatch-ить.

В общем пока сижу, тупо смотрю в экран, и очень стараюсь понять, что же собственно нужно.

malandrinus,

а "символы строки" определить, как противоположность "символов разделителей"

Вот это и пытаюсь. Но, похоже, что-то не то делаю. Не работает.

 

Gun12, разделители известны. Да, .* в lua работает не так, как надо мне.

По логике в lua должно быть что-то типа s1, s2 = string.match( s, "([^раздедитель]*)[разделитель]*(.*)" ) ), где разделителей несколько, но оно почему-то тоже не работает.

С разделителем из одного символа - работает. С одним или более из нескольких - нет.

Странно, у меня работает.

local sep = '%-!@#&|\\/><:;'
s = 'qwer<!--/#|||#/-->asdf'

s1, s2 = s:match("([^"..sep.."]*)["..sep.."]*(.*)" )
print(s1) --> qwer
print(s2) --> asdf
Изменено пользователем Gun12

Ну так я же фактически так и написал в начале. Правильнее использовать не '*', а '+', поскольку требуется вхождение как минимум одного символа.

 

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

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

О, кажется, я понял:

То есть, надо писать именно [^"строка"], а не [^символ^символ^символ] ?

 

А конфиги трогать нельзя. Это будет оскорбление чуйств верующих.

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

Первый вариант я хотел написать :

s1, s2 = s:match( '(.-)['..sep..']+(.*)' )

Но у второго шире спектр действия. Как раз из-за того, что не ограничивает в обязательном наличии.

Будет строка вида :

s = 'qwer' -- или s = 'qwer<!--/#|||#/-->'

найдёт хотя бы qwer

. Или типа :

s = '<!--/#|||#/-->asdf'

то найдёт asdf

.

А с '+' при строке

s = 'qwer'

уже будет nil, хотя фактически-то хоть одна, но есть.

В общем, действительно, нужны более конкретные условия. Под них и подстраиваться.

а не [^символ^символ^символ]

Так ведь в руководстве чётко написано :


[^set]: Отрицательный набор символов!

Можно написать и (шутка конечно)

s1,s2 = s:match("([^!@#&%-!@#&|\\/><:;]*)[!@#&%-!@#&|\\/><:;]*(.*)")
Изменено пользователем Gun12

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

Вот пример:

function func (value)
    print (value)
end

tbl = {}

function Past(f,v)
    tbl[f]={v=v}
end

function OnPrint()
    func2 = func
    func3 = func
    Past (func2, "two")
    Past (func3, "three")
    for fun,val in pairs (tbl) do
        fun(val.v)
    end
end
При вызове функции OnPrint, естественно, в качестве результата я вижу лишь "three", т.к. func2 и func3 это ссылки на func.

Вопрос: можно ли подправить код так, чтобы в результатах отобразилась и "two" и "three" без явного вызова функции func в функциях func2 и func3?

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

Что-то ты перемудрил :) Почему просто не вызвать func(v)? Безо всяких таблиц.

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

Если меняются только аргументы, так для каждой функции и создавай таблицу этих параметров:

tbl = {}

function Past(f,v)
    if not tbl[f] then
        tbl[f] = {}
    end
    table.insert(tbl[f], v)
end

function OnPrint()
    func2 = func
    func3 = func
    Past (func2, "two")
    Past (func3, "three")
    for fun,vals in pairs (tbl) do
        for i,val in pairs(vals) do
            fun(val)
        end
    end
end
Извиняюсь, если не уловил суть вопроса.

@abramcumner, не очень понял о чём Вы.


@Shredder, при таком подходе не получится удалить один элемент из таблицы таким образом:

tbl[f] = nil
Т.к. удаляться они будут по отдельности, а так выйдет все скопом.
  • Нравится 1

CoIR_IT

Создавай функции с помощью замыкания. Если никто не подскажет конкретно, то сделаю это чуть позже. Сейчас я с телефона.

@ColR_iT,

Я тоже не совсем понимаю зачем тебе одинаковые функции, но ради академического интереса можно и решить :)

На самом деле есть несколько вариантов решения, но не зная общего замысла, дам один из вариантов для частного случая :

local t = {}

function getf(arg)
    local function f(x)
        print(x)
    end
    t[f] = arg
    return f
end


func_1 = getf(3)
func_2 = getf(4)
func_3 = getf(5)

for k,v in pairs(t) do
    k(v)
end

Или :

local t = {}

function getf(arg)
    local function f()
        print(arg)
    end
    t[f] = true
    return f
end


func_1 = getf(3)
func_2 = getf(4)
func_3 = getf(5)

for k in pairs(t) do
    k()
end
Изменено пользователем Gun12

ColR_iT,

У меня есть шесть абсолютно одинаковых функций

Возвращаясь к исходному вопросу. Мне непонятно вот что. Если у тебя шесть одинаковых функций, то зачем они вообще нужны, шесть одинаковых? Почему не одна? Производный отсюда вопрос. Если они одинаковые, то естественно использовать их в качестве ключа не получится, это одно значение. Но и вообще, зачем хранить шесть ссылок на одну и туже функцию? Храни только разные данные, а функцию (одну) вызывай по глобальной ссылке. Если же надо, чтобы при вызове шести этих функций делалось что-то разное, то тогда либо таки создавать разные функции, замыкание или динамическая компиляция из составляемых строк в помощь, либо используй метод объекта (или перегруженный оператор вызова объекта, т.е. функциональный объект) примерно с тем же эффектом.

Вообще же, без пояснения, зачем это надо, сложно что-то обсуждать. Конечная задача совершенно неочевидна.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Тупанул, когда не объяснил всей сути, признаю...

Если кто знаком с файлом xr_s.script, то тому код будет знаком. :)

У меня есть в целом вот такая конструкция:

tbl = {}

function Register(f,v)
    tbl[f]={v=v}
end

function Unregister (f)
    tbl[f]=nil
end
--#---------
function update ()
    for func,param in pairs(tbl) do
        func(param.v)    
    end
end
--#---------
function func2 (value)
    print (value)
end
function func3 (value)
    print (value)
end

function Past()
    Register (func2, "two")
    Register (func3, "three")
end
Функции func2 и func3 вносятся в таблицу tbl посредством функции Register, это я делаю в нужный мне момент. Функция update периодически обновляется и тем самым апдейтит обе мои функции func2 и func3. Когда мне не нужно обновлять, например, функцию func2, я вызываю функцию Unregister(func2) и тем самым оставляю в биндящейся функции, а точнее в таблице, итерация которой находится там, лишь func3.

Со временем функции func2 и func3 разрослись (к тому же их не две, а шесть) и стали изрядно занимать место. Т.к. функции имеют одинаковое тело, то я подумал, почему бы не сократить код до одной "общей" функции, а передавать ссылку на неё шести другим (к сожалению, передачи по значению в Lua нет), но столкнулся с проблемой, которую не смог обойти, скажем так, изящнее, нежели вызывать одну общую функцию внутри этих шести, на манер такого:

function func (value)
    print(value)
end

function func2(value)
    func(value)
end
function func3(value)
    func(value)
end
Имхо, не комильфо.

А проблема со ссылкой, думаю, ясна - в таблице tbl, при использовании Register будет всегда одна и тот же ключ. От чего и попросил Вашего совета. :)

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

ColR_iT,
сделай регистрацию не по самой функции, а по некому имени. Т.е. заведи ключ в виде строки, а саму ссылку на функцию помести в ту же таблицу, где и аргумент.
 

tbl = {}

function Register(call_name,f,v)
    tbl[call_name]={f=f, v=v}
end

function Unregister (call_name)
    tbl[call_name]=nil
end
--#---------
function update ()
    for _,param in pairs(tbl) do
        param.f(param.v)    
    end
end
Изменено пользователем malandrinus
  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Или твой вариант, но с замыканием :

tbl = {}

function Register(f,v)
    tbl[f]={v=v}
end

function Unregister (f)
    tbl[f]=nil
end
--#---------
function update ()
    for func,param in pairs(tbl) do
        func(param.v)    
    end
end
--#---------
function getf()
    return function(arg)
        print(arg)
    end
end
----------------------------
func2 = getf()
func3 = getf()

function Past()
    Register (func2, "two")
    Register (func3, "three")
end
  • Нравится 1

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

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

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

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

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

Войти

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

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

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