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

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


Malandrinus

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

Viнt@rь, ну у меня и используется цикл в той реализации, что я выкладывала. При срабатывании таймера, не только находим тот, который будет выполнен в следующий раз, но еще и смотрим, есть ли еще такие, что должны сработать сейчас? Если есть - отрабатываем их. Однако в реализации Gun12 это чревато нагромождением кода, лучше уж рекурсию допустить.

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

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

 

Добавлено через 4 мин.:

Тема, кстати, тоже хорошая - циклы vs рекурсия. Выбор должен определяться условиями и окружением твоего кода, а не личными предпочтениями. Имхо.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

И правильно думал, что вероятность... :) Она действительно мала в реальных условиях. Учитывая архитектуру твоего кода, это можно делать через рекурсию.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Gun12,

type(tonumber(time)) == 'number'

Хм. А это что за покемон? В чем сакральный смысл?

Я просто в восторге. Аж дух захватывает.

Это здорово. Что сам думаешь про такой подход вместо createTimer(xxx,xxx,xxx)?

На самом деле, тоже въехала в код, в который раз ЛУА меня удивил своими возможностями. Финты ушами такие можно делать, что мама не горюй. У тебя практически уже около ООП что-то: есть "описание класса" timer, и есть "конструктор" __call. И работаешь с инстансами. Круто. Чуть-чуть доработать и будет почти тот же функционал, что дает луабинд :)

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
Не хочу, чтобы сюда попали другие данные, кроме числа.

А ты посмотри, что ты делаешь :) Сначала приводишь параметр к числу и проверяешь, число ли у тебя... Ну конечно число! Ты же только что приведение типа сделал :) Не нужен там tonumber, он тебе всю твою задумку ломает. Ибо type(tonгmber(x)) всегда 'number'

Двойка мне за знание матчасти. Все верно у тебя. Вот еще один нюанс луа с приведением типов обнаружился...

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Это немного отличается от того, как сделано в луабинде. Там все намного более семантично сделано.

В твоем примере ты получаешь "класс", вызвав функцию class(). Это не является определением класса, имею ввиду, что это не общепринятый синтаксис, как во многих других языках. Стандартно пишется "ключевое слово", обозначающее, что сейчас будет определен класс, а потом - имя класса. Зачастую идет третий "параметр" - родительский(ие) класс(ы).

Суть в ЛУА не меняется. Эта информация так, для общего развития. Лично мне просто привычнее работать именно так, после С++, Java, Питона, ПХП. В Javascript используется прототипирование, там вообще все по-другому, как раз больше похоже на то, что ты описал.

Может оффтоп, а может информация для общего развития :)

ИМХО, такое нужно применять для чего-то более масштабного чем таймеры в моей интерпритации :

Лично мне такой способ объявления "дочерних классов" очень неудобен. Но это именно мое имхо и мои привычки. Но ООП на этом действительно можно спокойно реализовывать. И вообще, я где-то говорила, что это проблема? :) Луабинд все это реализовывает именно таким вот хитрым путем. Принцип его работы очень легко повторить.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Попрошу не путать :) Луабинд ничего не добавляет к луа. Он реализует, образно говоря, некий функционал, используя только возможности самого луа. Если очень приспичит, я могу написать обертку, которая будет делать практически то же самое, что и луабинд - предоставлять возмжность создавать "классы" и реализовывать "наследование". Там всего-то две функции, а остальное игра с метатаблицами. Смысла только не вижу. Если хочется обсудить принцип реализации луабиндом этой фишки - прошу в личку. Еще раз - луабинд НИКАК не расширяет синтаксис ЛУА, а просто имеет "встроенный" дополнительный функционал. Вот что главное.

------------------------

Вывод всего этого - метатблицы и переопределение операторов - рулез.

 

Добавлено через 5 мин.:

А вообще, понятие "чистый ЛУА" смысла не имеет. Если вспомнить, что можно к интерпретатору подключать различные библиотеки, "базовая" комплектация содержит только самое основное. Никто не гнушается подключать библиотеки к интерпретатору. Потому мне кажется, что твое желание "изучить чистый ЛУА" не сильно логично. Лучше уж знать максимум, исопльзовать что нужно для своих целей исходя из задач.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Gun12, Viнt@rь, вот для общего развития. Реализация "классов", подобная реализации луабинд. Можно "наследовать" классы, форма записи - такая же (определение классов).

Как видно из кода - реализация примитивнейшая средствами ЛУА, но результат...

_G.class = function (cls_name)
    if type(cls_name)~='string' then
        return function() end
    end
    
    local cls = {}
    local cls_mt = {}
    cls_mt.__call = function(...)
    
        local cls_obj = {
            parent = cls_mt.__index            -- imitate parent class, allows call parent's methods
        }
        local cls_obj_mt = { 
            __index = cls,
            __gc = function () 
                if cls_obj.__finalize then
                    cls_obj:__finalize()    -- imitate destructor
                end    
            end
        }
        
        setmetatable(cls_obj, cls_obj_mt)
        
        if cls_obj.__init then
            cls_obj:__init(...)                -- imitate constructor
        end
        
        return cls_obj
    end

    setmetatable(cls, cls_mt)
    
    _G[cls_name] = cls
    
    return function(parent_cls)
        cls_mt.__index = parent_cls
    end
end

--================================================

class "A"

function A:__init()
    self.bar = "A says yahoo"
    print("A:__init called")
end

function A:foo()
    print("A:foo called")
end

function A:__finalize()
    print("A instance is destroyed")
end

---------
class "A_der" (A)    -- this class is derived from A

function A_der:__init()
    self.parent:__init()    -- calls parent method
    print("A_der:__init called")
end

function A_der:lol()
    print("A_der:lol called")
end

---------
class "B"

function B:__finalize()
    print("B instance is destroyed")
end

function B:__init()
    self.bar = "B says boooo"
    print("B:__init called")
end

function B:foo()
    print("B:foo called")
end

---------
local a = A_der()
local b = B()
a:foo()        -- calls A:foo
a:lol()        -- calls A_der:lol
b:foo()        -- calls B:foo
print(tostring(a.bar))
print(tostring(b.bar))
a = nil
b = nil
collectgarbage()

 

Функционал даже чуть-чуть шире, чем у той версии луабинда, что использована в сталкере.

У каждого объекта класса есть свойство self.parent, указывающее на "родительский класс", если такой есть. Это полезно, когда и в родительском и в дочернем классе существуют методы с одинаковыми именами. Можно вызвать из дочернего метода родительский. Редко бывает нужно, но бывает. self.parent:__init(...) абсолютно идентично super(...) в сталкере - вызов конструктора родительского класса (опять же - если есть). Ну и еще одно отличие - классы помещаются в глобальную область видимости.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Gun12

Что-то как-то громоздко. И я не понимаю интерфейса (имхо, тоже перегружен - мне кажется, геттеры и сеттеры в чистом виде не нужны. В "методы" обернуть бы более комплексную логику). Зачем ограничение, что таймер нельзя сохранять в переменной? Это не удобно, всегда присваивать имя. Это аналогично безымянным функциям - они есть, работают, можно передавать, но имени нет. ИМХО.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
Gun12, да никакого высшего пилотажа там нет :) Только синтаксис ЛУА. Класс - таблица-прототип, хранящая логику. Объект класса - тоже таблица, но хранящая данные. По метаметоду __index ссылается на таблицу-прототип. Наследование реализуется тоже с помощью __index - таблица-прототип ссылается на другу (другой класс) получая оттуда другую логику. Элементарно.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Andrey07071977,

Как быть в ситуациях когда в классе несколько методов которые необходимо подписать на разные события? Например, есть класс "actor_hit_effect", в нем два метода-подписчика - один на actor_hit, другой на item_use. Или же я что-то недопонял?

Использовать замыкания. Я раньше писала, как это делать. Я не знаю, зачем такие сложности Саша придумал :)

Вот вариант:

function bind_method_x(obj)
    return function (...)
        return obj:method_x(...)
    end
end

local funct = bind_method_x(megaobject) --в переменной funct окажется функция, которую можно передать куда угодно.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Andrey07071977, http://www.amk-team.ru/forum/index.php?s=&...st&p=661284

Там более развернуто, с созданием переменных, но это не обязательно. Пример выше - гораздо компактнее. Но делает то же самое.

 

Добавлено через 5 мин.:

Да, правильно. Можно, правда, еще короче:

function object_execute(obj)
    return function (...)
        return obj:execute(...)
    end
end
function object_execute_1(obj)
    return function (...)
        return obj:execute_1(...)
    end
end

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Andrey07071977,

Разве это не проверка перед сохранением?

А смысл мне от этой проверки? Это проверяется при сохранении и получаем ошибку.

Функция set была изначально организована так, что возвращала булевое значение - успешность помещения переменной в хранилище. Тогда, программист, получив false, мог бы принять меры - уменьшить как-то размер таблицы. (Черт! Надо еще длину у строки проверять!) А так. Он запихнул, а потом огреб ошибку, и как ее обрабатывать?

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Саш, дополнительные параметры в инетрфейсе, использование метатаблиц - это не сложности? По сравнению с одним единственным замыканием - еще какие.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
Andrey07071977, прикол в том, что боттлнека, кстати, не будет при таком подходе: при set производится одна сериализация, при сохранении в "оптимизированном" варианте - при сохранении сериализуется все. В первом подходе нагрузка распределена по времени. И влияние на производительность оказывает небольшое. Зато мы сразу предупреждаем программиста - у тебя тут гавно, срочно принимай меры.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Саш, peace :) Просто ты привел такие примеры.

Ну а насчет интерфейсов я все равно настаиваю, что они должны быть как можно проще и как можно меньше вариаций иметь

 

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Объект и биндер - Саша делал. В коде указано же было.

 

Добавлено через 25 мин.:

Только вот прописывать их в АСДС смысла нет. Они спавнятся только скриптами. В редакторе не имеют вообще никакого визуала и не несут никакой нагрузки. То есть в спавне им делать в принципе нечего.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

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

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

Но это просто имхо, чтоб ты знал его :)

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

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Так, доработка по библиотеке пакетов. Мануала все ще нет, но как допроверю, что все ок, будет.

http://dl.dropbox.com/u/46539648/xs_netpk.script

1) Да, оно завязано на мою песочницу, так что надо прописать, если используется эта песочница.

2) Кто любит все переделывать, типа Artosa, могут так же переделать и это, суть понятна, мне кажется.

Собственно, какие изменения:

Попробовала учесть все замечания по неправильному содержимому пакетов, опечатки и прочее.

Добавлен класс для работы с абстрактной частью пакетов - описание в шапке файла.

ЗЫ Да, лакончино, скомкано и т.п. Все будет развернуто, когда доберусь до мануала. А пока тот, кто понимает, прошу вас это посмотреть, потестить. Нужен фидбек по ошибкам. Заранее спасибо.

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

abramcumner, что такое bind в переводе с английского?

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

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение

Еще раз - советую вспомнить/посмотреть перевод слова bind. Хорошенько вникнуть.

Для аналогии и стимуляции мышления могу подкинуть слово 'luabind'.

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

Все, кто стоит на моем пути: идите нахрен и там погибните! ©

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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