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

Язык 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
Ссылка на комментарий

@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 пользователей

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