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

Язык 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 tabl = {
    ["t1"]      = {{"s1",40},{"s2",25},{"s3",5}},
    ["t2"]      = {{"x1",40},{"x2",30},{"x3",5}},
    ["t3"]     = {{"z1",40},{"z2",40},{"z3",5}}

}

и есть такая функция

local sec = rnd(tabl[key]) -- key = t1 or t2 or t3
function rnd(t)
    local sum = 0
    local rand = math.random(100)
    for i,v in ipairs(t) do
        sum = sum + v[2]
        if rand <= sum then
        return v[1]
        end
    end
end

Выдаёт ошибку bad argument #1 to 'ipairs' (table expected, got nil)

Что я делаю не так? Пожалуйста, подскажите. Заранее спасибо.

 

Когда умрёшь, увидишь кнопки

"О'кей" и "Главное меню"
Под ними "Новая" и "Выход"

И неактивная "Назад"

 

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

toxictrace, а ты уверен, что в качестве key ты передаёшь то, что нужно? Это единственная причина подобной ошибки.

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

Если math.random(100) , скажем для таблицы t2 будет в пределах 76-100, то функция rnd возвратит nil. Так и задумано?

И я бы использовал перебор for i=1,#t do
Процентов до 30 быстрее.

Изменено пользователем ColR_iT
Ссылка на комментарий
И я бы использовал перебор for i=1,#t do

В этом случае вылетаем с attempt to get length of local 't' (a nil value)

 

то функция rnd возвратит nil. Так и задумано?

Нет, конечно. Просто не так поставлено. Это для примера

 

что в качестве key ты передаёшь то, что нужно?

Проверил, действительно, не все данные были правильными. Но, к сожалению, после исправления вылет остался.

 

Вопрос решил. Можно не париться. @ColR_iT, спасибо за наводку. Ты оказался прав.

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

Когда умрёшь, увидишь кнопки

"О'кей" и "Главное меню"
Под ними "Новая" и "Выход"

И неактивная "Назад"

 

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

А почему ты написал "Но при этом"?

Классы реализованы с помощью таблиц, нет?

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

Real Wolf, в Lua по другому то и не выйдет. К сожалению, я не знаю механизма реализации наследования в LuaBind, но мне кажется, что от обычного Lua'шного способа с копированием таблиц и метатаблиц он не сильно отличается. LuaBind это ведь "обёртка", упрощающая написание кода или я ошибаюсь?

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

Как раз то в том и фишка, что никакого копирования нет.

Вопрос, - "...что же этой строке происходит с точки зрения Lua?" был не зря задан. И ответ на него поясняет способ создания того же наследования.

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

Real Wolf,

Классы реализованы с помощью таблиц, нет?

В Luabind - на userobject.

ColR_iT,

LuaBind это ведь "обёртка", упрощающая написание кода или я ошибаюсь?

Ну вообще-то это некислый api для связи C/C++ кода с Lua. Это его основное назначение. Разумеется, если мы этим не занимаемся и ограничены рамками Lua, то нам остаётся доступен в качестве полезного сервиса только небольшой кусочек, помогающий строить (псевдо)классы. Обёртка? Это на мой взгляд неправильный термин здесь. Не обёртка, а расширение. Очень специфическая библиотека.

Gun12,

Как раз то в том и фишка, что никакого копирования нет.
Вопрос, - "...что же этой строке происходит с точки зрения Lua?" был не зря задан. И ответ на него поясняет способ создания того же наследования.


Мне кажется, вы все усложняете мой вопрос. Если помните, то вопрос был вызван тем, что всплыл редко используемый синтаксис вызова функции function_name{<arguments>}. В связи с этим я и предложил интересующимся подумать над синтаксисом строки объявления класса. Я только хотел сказать, что такой код:
 

class "new_class_name" (existing_class)

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

Вопрос же, что там делает Luabind, выходит за рамки данного обсуждения, поскольку это Luabind, он от нас скрыт. В том числе вопрос есть там копирование или нет. Вообще-то есть, как же иначе мы скопируем методы базового класса в унаследованный. Другое дело, как оно технически происходит, что Luabind там внутри себя делает с метатаблицами и пр. - это уже другой вопрос.

 

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

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

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

 

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

как же иначе мы скопируем методы базового класса в унаследованный

А на кой эти методы копировать?

Не знаю как там именно в Luabind устроено, но во всех расширениях, имитирующих luabind,  унаследованный класс индексируется на базовый.

Там и найдёт нужные методы, если нужно, без всякого копирования. Иначе теряется весь смысл ООП.

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

Gun12,

 

 

Иначе теряется весь смысл ООП

Хм. А в чём смысл ООП?

 

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

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

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

 

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

Gun12, и какое отношение смысл ООП имеет к делегированию или каскадированию методов? В прототипном ООП используются оба подхода. Чем выбор одного из них может противоречить основам ООП?

 

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

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

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

 

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

Да я то, лично, не против. Способов действительно не мало.

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

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

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

Что же касается Luabind, то это в сущности и не прототипное ООП в чистом виде, а ближе к имитации класс-ориентированного подхода, поскольку добавляется класс как самостоятельная именованная сущность. Мы этот класс не используем сам по себе, а создаём экземпляры этого класса, используя вызов class_name(<аргументы>). При этом экземпляры класса, хоть и userdata, но технически отличаются от самого класса, который тоже userdata, но специальный. Соответственно, есть два различимых этапа работы с классом: конструирование класса и работа с объектами класса. В связи с этим всё становится совсем весело, поскольку в любой момент мы можем изменить: базовый класс, унаследованный класс, экземпляр базового класса, экземпляр унаследованного.

Я проверил влияние изменений одного на другое в разных сочетаниях. Выходит что:
1. Никакие изменения ни базового класса ни его экземпляров не сказываются на унаследованном классе и его экземплярах после выполнения наследования. Значит при наследовании выполняется копирование (делегирование) методов.
2. Изменения класса однако сказывается на экземплярах этого класса уже после того, как экземпляр был создан. Значит в процессе создания экземпляра класса выполняется каскадное прототипирование. Но это обстоятельство не так уж и интересно. П.1 гораздо важнее.

 

Так что в целом выходит, в Luabind при наследовании методы копируются.

При этом я не уверен, что это справедливо для всех версий Luabind. По крайней мере это так в сталкеровской версии.

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

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

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

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

 

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

@Malandrinus,

а как ты проверял пункты 1, 2?

По-моему снаружи оба метода должны давать одинаковые результаты. Разница в памяти/скорости работа.

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

abramcumner,

а как ты проверял пункты 1, 2?

Пожалуйста:

Определяем class1 и class2, унаследованный от class1

class "class1"
function class1:__init()
end
function class1:fun()
    log1("fun 1")
end

class "class2" (class1)
function class2:__init()
end

создаём экземпляры классов

local a1 = class1()
local a2 = class2()

вызываем методы

a1:fun() -- fun 1
a2:fun() -- fun 1

Результат пока вполне ожидаемый. Вызывается один и тот же метод.

Теперь переопределяем метод класса class1

function class1:fun()
    log1("fun 2")
end

Проверяем:

a1:fun() -- fun 2
a2:fun() -- fun 1

Метод унаследованного класса не изменился, зато изменился метод базового. Это повлияло и на экземпляр класса.

Теперь заменяем метод не класса, а экземпляра класса

function a1:fun()
    log1("fun 3")
end

Проверяем:

a1:fun() -- fun 3
a2:fun() -- fun 1

Унаследованный, как и раньше, не поменялся. Метод конкретного этого экземпляра изменился.

Проверяем, как изменение метода экземпляра повлияло на класс.

Создаём экземпляры заново.

local b1 = class1()
local b2 = class2()

Проверяем

b1:fun() -- fun 2
b2:fun() -- fun 1

Т.е. изменение метода экземпляра на сам класс не повлияло. Здесь в принципе работает прототипное ООП.

 

По-моему снаружи оба метода должны давать одинаковые результаты. Разница в памяти/скорости работа.

Ну если я не пытаюсь менять уже сделанные классы/объекты, то внешне разницы никакой. Разница возникает, если я пытаюсь менять определения классов или менять заменять методы экземпляров уже во время выполнения, вот как выше показано к примеру. Там конечно искусственная ситуация и на мой взгляд, не так уж много выгоды вообще в попытках менять классы. Хотя этого категорично утверждать и не буду, но я не встречал задач, где это реально могло бы принести пользу.

 

 

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

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

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

 

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

Помогите, плиз, с регэкспом для string.match: "(все, что не charset)(все, что после charset)"

Оно такое вообще возможно ?

 

Пример: на входе имеем "а_вот_такая_вот_фигня_1 | и_вот_такая_2", надо получить отдельно "а_вот_такая_вот_фигня_1" и "и_вот_такая_2", но на самом деле они могут быть разделены чем угодно, и известно только то, что собственно символов разделителя в искомых подстроках нет. Ага, разделителем может быть несколько символов в любом количестве и последовательности. В подстроках могут быть вообще любые символы, кроме символов, входящих в состав разделителя.

 

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

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

Боюсь что не смогу точно ответить. Если не трудно, покажи 'например'.

 

Т.е. нужно разделить неизвестно что по неизвестно чему?

Точнее есть одно более-менее конкретное условие - 'символов разделителя в искомых подстроках нет'.

Только оно ещё более усугубляет картину. Второй же символ строки в 99% случаев окажется не таким как первый, вот и может считаться разделителем.

В общем либо я чего-то не понял, либо это действительно невозможно.

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

Dennis_Chikin,

типа такого не пойдёт?

 

 

s1, s2 = s:match("([%wа-яА-Я_]+)[^%wа-яА-Я_]+([%wа-яА-Я_]+)")
 

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

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

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

 

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

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

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

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

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

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

Войти

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

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

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