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

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

Вот не хотел же влезать :) Всё это надо читать в документации, а не хватать по форумам.

Луа:

2.1

  Цитата

В Луа 8 типов: nil, boolean, number, string, function, userdata, thread, and table

Из них 4 типа: nil, boolean, number, string - являются типами-значениями. Это значит, например, что при передаче в функцию, передается их копия.

function f(a)
  a = 5
end
local x = 7
f(x)
print(x) -- выведет 7, потому что в функцию передалась копия
Оставшиеся 4 типа: function, userdata, thread, and table в документации луа названы "objects" - я бы сказал по-русски ссылочный тип. Перменные таких типов хранят не сами значения, а ссылки на них.

function g(a)
  a.y = 5
end
local x = {y = 7}
g(x)
print(x.y) -- выведет 5, потому что в функцию передалась ссылка и по этой ссылки значения можно менять.
Если программист до луа изучал си , то все ссылочные типы можно воспринимать как константные указатели, чем они на самом деле и являются. Правда константных указателей в C вроде не было, они только в C++ появились :)
Ссылка на комментарий
  19.04.2015 в 10:15, Dennis_Chikin сказал:

Опс... Что-то про string я захотел посмотреть код. Точнее, много кода. Если это действительно так, то я перестаю понимать, как работает многое из того, что работает. Ну вот в частности вообще все таблицы.

Замени в примерах выше числа на строки: 5 на "aa", 7 на "bb". Ничего не изменится.

Приводи код, который непонятно работает.

Ссылка на комментарий
  abramcumner писал(а):

выведет 7, потому что в функцию передалась копия

Да, но почему этот пример такой? Вот сразу же дальше для ссылочных типов ты верно все пишешь, но если использовать функцию f(a) для них, тоже магии не произойдет, потому что ты переопределяешь аргумент, наружу это никак не уйдет в любом случае, будь там хоть value type хоть reference type.

  Карлан писал(а):

как-бы в сталкере они связаны

Это не дает нам права разводить откровенный оффтоп. Тут C++, и он закончился в начале этой страницы, но я надеюсь тред будет перенесен в тему Lua.
  • Согласен 1

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий
@Desertir,
  19.04.2015 в 11:22, Desertir сказал:

Да, но почему этот пример такой? Вот сразу же дальше для ссылочных типов ты верно все пишешь, но если использовать функцию f(a) для них, тоже магии не произойдет, потому что ты переопределяешь аргумент, наружу это никак не уйдет в любом случае, будь там хоть value type хоть reference type.

Не понял. Приведи другой пример... Я просто показал, что в луа есть типы-значения и ссылочные типы и чем они отличаются. Ну и у ссылочных типов в луа семантика указателей.
Ссылка на комментарий

local test_s1 = ""

local test_s2 = ""

local test_i = 0

 

function test( v ) end

 

for i = 1, 10000 do test_s1 = test_s1 .. " " end

 

local pt = profile_timer()

pt:start()

for i = 1, 10000 do test ( test_s1 ) end

pt:stop()

log( "info", "string 200000: %s", pt:time() )

 

local pt = profile_timer()

pt:start()

for i = 1, 10000 do test ( test_s2 ) end

pt:stop()

log( "info", "string 0: %s", pt:time() )

 

local pt = profile_timer()

pt:start()

for i = 1, 10000 do test ( test_i ) end

pt:stop()

log( "info", "int: %s", pt:time() )

 

 

string 200000: 30992.1328125

string 0: 231.48368835449

int: 216.08390808105

 

Таки да, действительно копирует. Прощай очередной "оптимизаторский" миф про "строки существуют только в одном экземпляре".

Ссылка на комментарий
  abramcumner писал(а):

Не понял. Приведи другой пример...

Показать, что value type передаются по значению? У меня только 1 вариант приходит в голову, это надо получить их адреса и показать, что они разные. Но я не знаю как это сделать :)print variable address lua

 

@Dennis_Chikin, омг, да ты о чем? Сам же приплетаешь способы передачи аргументов и сборщик, это к чему вообще? Есть 2 типа переменных - value type и reference type. Первый при передачи в функцию копируется, второй нет. У value type адреса будут отличаться, у reference type нет. Все. Точка. Никаких присваиваний, созданий переменных и прочей лабуды.

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

ТЧ 1.0004. SAP и Trans mod

github

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

2 Desertir: только код смотреть. Адреса же нам принципиально не показывают в явном виде.

 

Собственно, имея в виду (господи, как же это и назвать-то теперь, чтоб очередной страницы флуда не получить) - ну, вы поняли - я бы вообще сделал банально:

 

Если что-то передается в функцию - передается адрес (у нас внутри все равно не регистровые операции, а если и регистровые, то с предварительной загрузкой из стека). То есть, пока нет присваивания - по этому адресу и получаем. Как только присваивание - создаем новую переменную, и указатель выставляем на нее.

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

 

 

2 abramcumner: ожидаемо, 246 для таблицы (vs 212 и 212 для "" и 0 ).

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

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

Этот метод также вызывает эту функцию. Т.е. мне нужно либо вызывать функцию внутри метода, либо вместо метода.

  Показать

 

 

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

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

@Xdlic, весьма странное поведение. Объясни что ты хочешь сделать, у меня чувство, что ты выбрал не совсем верную стратегию.

И еще, ты используешь LuaBind?

ТЧ 1.0004. SAP и Trans mod

github

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

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

Пока это все в виде набросков, но схема предложенного выше такова:

Есть класс (скажем 1), задачей которого являет обновление состояния массива объектов другого класса (2). В этом втором классе обновление может быть реализовано как в виде метода (при инициализации в метод inject подставляется нужный в данной ситуации метод), так и в виде функции (этот метод предназначен, в свою очередь для вызова сторонней функции).

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

function element_class:inject(...)
  self.fun(...)
end

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

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

Определение метода и его вызов, это просто сахар в Луа.

local some_object = { one = 1, two = 2 }

--определили метод с "сахаром"
function some_object:print_one()
    print("Print one: "..self.one)
end

--определили метод без "сахара"
some_object.print_two = function(self)
    print("Print two: "..self.two)
end

some_object:print_one() --Print one: 1
some_object:print_two() --Print two: 2

some_object.print_one(some_object) --Print one: 1
some_object.print_two(some_object) --Print two: 2

--если так сильно надо заменить метод и чтобы он оставался методом, можно сделать так
function print_three(self)
    print("Print three: "..self.three)
end

some_object.three = 3
some_object.print_two = print_three --пошалим

some_object:print_two() --Print three: 3
some_object.print_two(some_object) --Print three: 3
Так можно сделать, но это скорее всего приведет к багам или "непредвиденным последствиям" (с). Для изменения поведения есть условные ветвления.

ТЧ 1.0004. SAP и Trans mod

github

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

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

 

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

 

@Desertir, это очень грубо и я бы даже сказал несуразно.

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

@Карлан, переопределение метода вообще моветон. Ктото из команды написал метод paint а ты его переопределяешь, и пишешь туда сложение, а тот первый пытается чтото вывести на экран. Получается вообще не пойми что и огрести можно не слабо. Я резко против этого, поэтому и написал, что есть if ... then.

  Карлан писал(а):

я бы даже сказал несуразно

Про твой способ могу сказать тоже самое.

ТЧ 1.0004. SAP и Trans mod

github

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

@Desertir, :D с такими выводами можно функцию переписать с таким же успехом. В переопределении нельзя использовать if-then? Это не мой способ, но его для этого и создавали. Можно написать условия и для сложения и для вывода на экран, причем тут командная работа я вообще не понял.

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

 

    Это могло бы быть вариантом, но в целом в результате дает просто перенос выбора ветви поведения в другое место. Обработка вызова функции через метатаблицы по сути являются теми же ветвлениями, но они уже будут статичны для данного типа/класса.

 

  Desertir писал(а):

Определение метода и его вызов, это просто сахар в Луа.

 

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

 Следует отметить, что вызов inject-метода через точку не подразумевает передачу туда self в явном виде, во время вызова, иначе это скатилось бы к тем же громоздким ветвлениям.

 

  Desertir писал(а):

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

 

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

 

  Вопрос решен (Показать)
Изменено пользователем Xdlic
Ссылка на комментарий

   В ходе своих наработок в Lua для сталкера сделал отметил несколько любопытных моментов:

 

  Функции работы с индексированными массивами (Показать)
Изменено пользователем Xdlic
Ссылка на комментарий

@Xdlic

После выполнения 

for i = 1, #tb do tb[i] = nil end

у меня и в SciTE, и в игре функции insert и remove работают одинаково правильно, т.е. ставит 'value' в поле с индексом 1.

Покажи весь код, на котором ты тестировал и получал таблицу {nil, nil, nil, nil, nil, nil, nil, nil, nil, value}

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

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

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

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

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

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

Войти

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

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

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