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

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

Gun12, не стОит буквоедствовать... ;-) Цель моего поста не пытаться опровергнуть твои слова или указать на их "неправильность". Просто твоя фраза имеет сильно размытый смысл. Сам посуди, как может 'найденное вхождение' шаблона (иль строки) вообще заноситься a таблицу? Строго говоря (по-буквоедски), в таблицу заносится значение чего-либо, а не вхождение.

И тут могут быть два варианта:

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

б) заносятся куски строки, разделенные каждым 'вхождением шаблона', иначе, по каждому найденному вхождению шаблона

В варианте, который и присутствует в исходной функции, "волшебный символ" '^' как раз исключает сам разделитель (sDiv) из конечного результата и в итоге у таблицу попадают только куски строки с вырезанным из них разделителем и каждый не включает в себя ничего из предыдущего.

 

Dennis_Chikin, нет этот код не из АМК. Он был написан мною ("по мотивам АМК"!) для Simbion'а (и в нем используется), и был опубликован и на СП в топике по моддингу, откуда мог перекочевать куда угодно...

Раскомментировать этот код нельзя, т.к. патерн (шаблон) может иметь только одно значение. Т.о. кто-то мог не подумав заменить один патерн на другой... ну или взять код из давней версии мода.

Суть получается несколько различной - рабочий вариант фильтрует повторяющиеся пробелЫ, которые могут быть в исходной строке. А "твой" вариант - жестко требует наличия одного пробела после разделителя в каждом куске строки, что критично к формату написания строк в тех же конфигах.

Иначе: строка вида: str = "1,2, 3,   4 ,5" будет рабочим вариантом шаблона разделена по каждой запятой с исключением примыкающих пробелов, а вариант указанный тобою - споткнется там, где нет или не один пробел... 

 

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


P.S.

Кстати, а зачем объявлять локальную sValue='' в строке  local sPattern,sValue = "","" ?

Она и так локальна для цикла for.

Согласен, что она в данном случае лишняя... как и аргумент 'bNoErrLog' на входе в функцию. Но даже текущий код в моде пока еще недоделан и был написан с учетом "на вырост"...

В вычищенном виде это может выглядеть

function fSplitStrToTbl(sStr, sDiv, Mode)
  local tRet, sPattern = {}, '[%w%_]+' --/ шаблон для разделения строки на слова
  if sDiv and type(sDiv) == 'string' then --/ если divider задан:
    sPattern = '%s*([^'..sDiv..']+)%s*' --/ разделяем по нему с фильтрацией примыкающих пробелов
  end
... 

 

 

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

При чтении ltx white_spaces любого вида по-моему вообще игнорируются. SOC по крайней мере.

Сколько чего в лог не выводил - всегда идет что-то типа v1,v2,v3.

 

И есть шанс, что для %s пробел и табуляция тоже идентичны.

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

Dennis_Chikin, когда использование кода идет по принципу "мне кажется" или "вроде не замечал" - нет смысла говорить о программировании, а переходить к погадалкам в темах-ковырялках. ;-)

 

1. Если ты полностью полагаешься на корректность работы движка (в том числе и пропатченного  сторонними приблудами), читающего строки конфигов - можешь использовать и упрощенные шаблоны...

Но, напоминаю, мы в теме по общим вопросам Lua, и возможности встроенного в игру кастрированного компилятора могут как учитываться, так и игнорироваться читающими сей топик.

 

2. Не путай, дефолтное чтение движком игры отдельного параметра из строки ltx-конфига действительно выполняется с игнорированием пробелов и даже табуляторов (хотя есть метод чтения 'string_wq' - "как есть").

Однако(!), в данном случае рассматриваем случай, когда движок читает ВСЮ строку (значение параметра) из конфига, отсекая только начальные и заключительные пробелы , а распарсиваешь/разделяешь на куски уже ты "сам" указанной функцией. Причем, как строка (внутри себя), так и разделители в строке могут быть самого разного наполнения (, : | \\ и даже такой:'мой разделитель' и т.д.) о которых white_spaces и не подозревают.

 

3. Читая строки лог-файла не забывай, что они могут быть далеко не теми, которые ты задаешь скриптами... И пробелы могут как заменяться, так и обрывать строку, и сами символы переводиться в low... Все зависит от способа вывода в лог и корректности выполнения самим движком (компилятором). Если в SOC сами разработчики зарубили вывод в 

лог и мы пользуемся  суррогатами - можно ли это воспринимать как некое доказательство что видишь исходное?

"Не верь глазам своим...", а доверяй написанным тобою корректным кодам. ;-)

 

4. Патерн %s в Lua (и во многих других языках) означает строгое соответствие именно пробелу, а не абы "может и табулятору". Напомню, что есть еще и '\160' - безусловный пробел, который тоже никак не отсекается сей маскою. Так что "шансов" ни каких... ежели замусорил строку всяким мусором.



P.S. Вот пример заковырки с "простеньким" конфигом: IQ-test.ltx.

Попробуй считать движком/скриптами и разделить всего лишь пару параметров на их составные части из знаковых символов...  :crazy:

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Доброго времени суток.

И снова у меня вопрос из разряда элементарных-дурацких, но все же...

:)

Теперь решила сделать себе напоминалку праздников и дней рождения и все работает, но не могу разобраться, как удалить запись из таблицы. Собственно код

 

 

-- ["ММДД"] = {"Название праздника"," Описание либо имя","Год"}
table_1 = {
-- Январь
["0101"]    = {"День Рождения","Имя1","1988"},
["0131"]    = {"День Рождения","Имя1","1989"},
-- Февраль
["0201"]    = {"День Рождения","Имя1","1990"},
["0223"]    = {"День защитника отечества","текст"}
-- И так далее...
}

function Update()
    local y = SKIN:GetMeasure('Ms_Time_Year'):GetStringValue() -- Получаем год
    local m = SKIN:GetMeasure('Ms_Time_Month'):GetStringValue() -- Получаем месяц
    local d = SKIN:GetMeasure('Ms_Time_Day'):GetStringValue() -- Получаем день
    str = table_1[m..d]
    if str ~= nil then
        local tip = str[1]
        local nick = str[2]
        local yb = str[3]
        if yb ~= nil then
            age = tonumber(y) - tonumber(yb)
            msg = tip.."\n"..nick.."\nИсполнилось "..age
        else
            msg = tip.."\n"..nick
        end
        SKIN:Bang('!ShowMeterGroup Group1')
        SKIN:Bang('!SetOption', 'm_Script', 'Text', msg)
        return 1
    end
end

function NoRemind()
    table.remove(table_1, ???)

end

 

 

Вот не могу разобраться, как из таблицы удалить запись

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

userbar368.png

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

Callisto, в любом маломальском пособии по Lua, есть исчерпывающая информация по табличным функциям.

table.remove (table, pos)
Первый аргумент (обязательный) - это таблица из которой происходит удаление.

Второй (необязательный) - это позиция с которой нужно удалить элемент таблицы. Если параметр не указывать, то удалит последний элемент таблицы. При удалении, индексы элементов выше, сдвигаются вниз.

Работает только с индексированными таблицами.

 

В твоём же случае нужно присваивать ключу, значение которое ты хочешь удалить, значение nil. Например:

table_1.0201 = nil
На Wiki есть неплохая статья по таблицам за авторством iDreD: >>ClicK Me<<, есть что почитать...
  • Нравится 1
Ссылка на комментарий

Когда-то давно попалась мне эта статья ещё в оригинале. Решил её исправить. В общем, как видели, начал писать, да духа не хватило. Если соберусь с силами - закончу.

 

Да. И в данном случае нужно писать:

table_1['0201'] = nil
Так это вроде как эквивалентная запись, разве нет!?

ColR_iT

 

Это "обман зрения" :)

Написав :

table_1.0201 = nil

Идёт обращение к ЧИСЛУ! - 0201

А по синтаксису lua к ключу, являющемуся числом, обращаются :

table_1[0201] = nil

Так что если мы хотим обратиться как строке, то остаётся только один вариант :

table_1['0201'] = nil
Изменено пользователем ColR_iT
  • Нравится 1
Ссылка на комментарий

table_1.0201 = nil

Мне выдалась ошибка на такой код, ну и по логике должна быть ошибка.

 

Да, я и вправду поддался на "оптический" обман. :)

ColR_iT

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

Gun12,

 

Написав :

table_1.0201 = nil
Идёт обращение к ЧИСЛУ! - 0201

Это не так. Хотя запись через точку и является "синтаксическим сахаром" для обычной индексации, но при этом накладываются ограничения на характер ключа. Это может быть только строка, при этом не любая, а такая, которая подчиняется правилам для имён переменных в Lua, т.е. начинается не с цифры и набор символов ограничен. Таким образом с использованием нотации с точкой просто технически невозможно идексировать чем-либо, кроме строки.

 

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

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

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

 

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

Придется "обучать" хоть как-то распознавать и заменять.

Если учитывать что у нас подавляющее большинство использует Windows, и подавляющее большинство, из этого большинства, использует кириллицу, то у подавляющего большинства, из последнего большинства, несомненно установлена кодировка ANSI 1251 (cp1251).

А если так, то обучать можно и не как-то, а красиво :

local _lower = string.lower
local _upper = string.upper

function string.lower(s)
    return _lower(s:gsub("([А-Я])",function(c) return string.char(c:byte()+32) end):gsub("Ё", "ё"))
end

function string.upper(s)
    return _upper(s:gsub("([а-я])",function(c) return string.char(c:byte()-32) end):gsub("ё", "Ё"))
end

Сюда можно присоединить и тех немногих, у кого стоит ISO 8859-5 (cp28595)

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

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

Совершенно случайно попалось на глаза ошибочное утверждение из поста 803

4. Патерн %s в Lua (и во многих других языках) означает строгое соответствие именно пробелу, а не абы "может и табулятору"

 

%s в Lua обозначает соответствие любому из пяти общепринятых пробельных символов.

А именно :

\009 или \t  - горизонтальная табуляция
\010 или \n - перевод строки
\011 или \v - вертикальная табуляция
\013 или \r - возврат каретки

\032           - символ пробела

 

Напр. в таком случае :

s = '\n\r\t\v ' -- или s='\009\010\011\013\032'
s = s:gsub('%s','')

длина строки s будет равно нулю.

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

Очень давно интересует вопрос, - "Почему в Lua, в котором назначают метатаблицы и метаметоды (пусть даже посредством debug) практически всем типам данных (конечно кроме типа "userdata", как уходящему корнями в С and Ko) , не делают подобного для таблиц? Только потому, что функции таблицы "table" и собственных методов могут слиться (посредством тех же метатаблиц) в одну структуру?

Так ведь debug тут не нужен, да и не так много функций той "table". И даже добавив свои, можно просто не называть методы собственных таблиц (классов) такими же именами. Только и всего.

А ведь можем иметь доступ к функциям таблицы "table", как к объектам, включая метаметоды событий.

Т.е. можно написать : local t = t1 + t2

Или : local t = t1:insert('str'):sort()
вместо :

for ... каждого элемента таблицы "t1" делать то...то...и то...пока не сделаешь...

И так может повторятся много раз.

Другими словами создать макрос (в мета-смысле), выполняющем многие подобные действия.

А если добавить к этому разницу в производительности кода (упомянутого последним) написанного новичком, и...(ну скажем) не новичком ))), то (тут не нужно быть провидцем) выгода последнего будет более чем очевидна.

P.S. Это не праздный вопрос. Я, для себя, такое сделал .

Просто интересно, ПОЧЕМУ так не сделано изначально? Может кто знает?

Изменено пользователем Gun12
Ссылка на комментарий
, ничего не понял.
 

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

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

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

 

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

Если короче, то почему не сделаны такие возможности для таблиц? :

local t1 = {1,2,3}
local t2 = {4,5,6}
local t = t1 + t2 -- на выходе суммы - таблица
t = t:insert(99):sort()

Только потому, что смешаются имена своих методов и функций таблицы 'table'?

Напр.у меня есть такая возможность (точнее не 'например', а она у меня действительно есть)

Создаю таблицу с методом :

local t = {}
function t:func() end

И вставляю в таблицу значение :

t:insert('str')

Так вот если вдруг я назову свой метод не function t:func() end , а function t:insert() end, то вызвав t:insert('str') произойдёт обращение к методу insert моей таблицы t, а не к функции insert глобальной таблицы 'table'. Т.е. глобальная функция перекроется моей. Под этим я подразумеваю - "смешаются имена своих методов и функций таблицы 'table'"

 

Теперь получается, что если не называть методы моей таблицы 't' именами - concat, remove, sort и остальных из таблицы _G.table, то вполне спокойно можно пользоваться методами, пример которых указан в самом вернем коде. Обращаться, посредством двоеточия, и к функциям моей таблицы, и к функциям _G.table.

 

И теперь вопрос - "Это единственная причина, почему так изначально не сделано в оригинальной библиотеке lua? Или существуют другие "подводные камни"? И если они есть, то хотелось бы узнать об этом".

 

P.S. Моя реализация этой возможности пока сбоев не даёт, но лучше узнать о предстоящих ошибках (если они, конечно, есть) и заранее принять меры.

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

,

Таблица, в отличие от тех же строк - это более универсальное средство. Возможно причина в том, что разрабы не хотели "засорять" универсальный элемент языка частными возможностями. В том числе не хотели, чтобы в каждой таблице присутствовали имена стандартных функций (все из набора часто используемых имён). Таблицы часто используют для построения классов. Включение функций из библиотеки "table" автоматом заблокирует такие широко используемые имена методов как insert, remove и sort. С другой стороны, если сильно надо, то ничто не мешает добавить эти стандартные методы самому.

 

добавил:

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

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

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

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

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

 

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

malandrinus

В том числе не хотели, чтобы в каждой таблице присутствовали имена стандартных функций

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

Если создаётся пустая таблица, то она и есть пустая.

Например. если раньше таблица создавалась :

local t = {}

то у меня создаётся :

local t = meta{}

Ни одной из функций _G.table там нет, как и ссылок на них. И никаких метатаблиц для t не установлено. (сказать по правде - они есть, только очень спрятаны, иначе был бы невозможен доступ к функциям _G.table). Т.е. при отсутствии ключа в таблице 't' поиск такового будет производиться в таблице _G.table

Прописывать в стандарте языка, что программист не может использовать ключи "insert", "remove" и т.д. ?

Это конечно неудобство. Не называть имена полей своего класса именами полей таблицы _G.table.

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

 

Ну да Бог с ним. Спасибо за ответ.

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

Gun12,
я опять тебя не понимаю.

local t = meta{}

что это за синтаксис?
 

Т.е. при отсутствии ключа в таблице 't' поиск такового будет производиться в таблице _G.table

Если при обращении к ключу "insert" я что-то получаю, чего я не записывал, то мне без разницы, есть там поле или это оператор индексирования сработал из метатаблицы. Для меня такая таблица становится непригодной к использованию.
 

Это конечно неудобство. Не называть имена полей своего класса именами полей таблицы _G.table.
Но ради расширения функционала я, например, готов на это пойти. Не так много тех имён, чтобы запомнить и не называть.

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

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

Ещё аргумент. Функции из table - это всего лишь библиотечные функции. Их можно выкинуть при желании и заменить на что-то другое. Синтаксис же таблиц как таковой - это основа языка. Даже из этих соображений фишка не выдерживает критики.

 

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

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

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

 

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

Что за синтаксис?

Нормальный синтаксис luа.

Вызывается функция 'mеtа' и в качестве единственного аргумента передается таблица. Что тут такого???

 

Остальные твои высказывания полностью обоснованы. Такой ответ и хотел услышать.

 

Ещё раз спасибо за внимание.

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

Gun12,

Вызывается функция 'mеtа' и в качестве единственного аргумента передается таблица. Что тут такого???

Не сразу очевидно, что "meta" - это функция, поскольку это довольно редко использующийся способ вызова.

 

 

Всем интересующимся,

Раз уж зашла речь о нетипичных вызовах. В эту степь предлагаю подумать (кто ещё не знает), что именно происходит при использовании вот такой конструкции:

class "class_name" (base_class)
Напоминаю, что это объявление псевдокласса при использовании расширения luabind. Здесь объявляется класс "class_name", производный от существующего класса "base_class". Но при этом данная строка - синтаксически корректная конструкция. Вопрос, что же этой строке происходит с точки зрения Lua? Изменено пользователем malandrinus
 

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

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

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

 

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

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

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

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

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

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

Войти

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

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

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