Pull to refresh

Comments 42

Кого вы считаете наиболее выдающимися людьми в сфере computer science?
Отношение к MoonScript (это такой CoffeeScript в мире Lua, достаточно популярный) и к расширениям языка вообще.
«Как вы относитесь к языкам Python, R, Julia?»
хехе :) тоже спросим, спасибо!
Какие программы или игры, которые используют Lua, вам нравятся больше всего?
непременно спросим, спасибо!
Почему начиная с 5, вроде бы, версии, были убраны метатаблицы по умолчанию.
То есть для строк и чисел, можно задать метатаблицу, а таблицы и userdata хоть и имеют индивидуальные метатаблицы, тем не менее всегда создаются с нулевой метатаблицей и её приходится руками задавать каждому экземпляру.
спасибо, интересный вопрос
Думаю, для скорости.
Ведь добавить можно много чего, но какой ценой?
При создании таблицы в OP_NEWTABLE вызывается luaH_new(), в котором t->metatable = NULL; а могло бы быть t->metatable = defaultmeta; (которая по умолчанию могла быть равна NULL) на скорость это особо не повлияет.
надо просто её где-то дополнительно хранить и задавать как-нибудь, как вариант добавить эту defaultmeta в библиотеку table.
Причиной может быть пожалуй некая запутанность и неочевидность кода, когда где-то задали эту метатаблицу по умолчанию, а потом совсем в другом месте строка {1,2,3} + {3,2,1} вместо сложения или ругани на арифметические действия с таблицами возьмёт и позовет os.system(«rm -rf /*»)

но иногда например хочется добавить таблицам арифметику по умолчанию (чтобы как в Mathematica), без создания каждой новой таблицы через отдельную функцию которая ей метатаблицу правильно задаст vec({1,2,3}) + vec({3,2,1})
ещё пожалуй одна фича которой не хватает, это чтобы из таблиц, особенно многомерных можно было брать куски как в той же математике
reference.wolfram.com/language/ref/Span.html

ну и наконец, почему нельзя взять элемент только что созданной таблицы {1,2,3,4,5}[3], а надо обязательно со скобками ({1,2,3,4,5})[3]
На скорость, хоть и не значительно, но всё же влияет. Заполнение нулями быстрее, чем копирование памяти. А ещё здесь речь про создание таблицы, которые в Луа на каждом шагу! То есть любое создание таблицы, даже вызов функции, будет делать дополнительную операцию. А теперь ещё вспомним про сборщик мусора, который должен учесть, что на метатаблицу появилась новая ссылка — еще одна операция (дай бог лишь одна, я точно не знаю, как там он устроен). То есть если defaultmeta == NULL, то ничего не делать, иначе увеличить счетчик на 1, это в самом простом виде.

Что касается синтаксического сахара, то на скорость работы скрипта он не влияет, но зато влияет на скорость компиляции. Опять же, не берусь сказать, насколько сильно. Но скорость компиляции важна. И я говорю не про использование функций типа loadstring во время выполнения, а про банальный запуск программы на Lua. Допустим, это тяжелая игра. Запуск в 10 секунд (с подвисанием) это плохо. Имхо, конечно.

Вообще мне сложно представить, где были бы реально полезны ваши пожелания по таблицам-литералам. Например, вместо {1,2,3,4,5}[3] можно написать просто 3. Зачем так сложно записывать? Более того, если написать degrees={1,2,3,4,5}, а потом использовать degrees[3], то логика программы становится яснее, уменьшается количество ошибок. Даже в вашем vec({1,2,3}) + vec({3,2,1}) проще разглядеть, что таблицы обозначают именно векторы, иначе остается гадать.
Речь вроде бы лишь про копирование единственного указателя вместо присваивания NULL, а не про заполнение нулями, но да, на пару тактов медленнее.
t->metatable = G(L)->mt[LUA_TTABLE]; вместо t->metatable = NULL;

Метатаблицы для типов (всех кроме таблиц и юзердаты) хранятся отдельно в global_State.mt.
Причем размер массива указателей на эти метатаблицы типов равен LUA_NUMTAGS и уже включает в себя метатаблицы «типов» также для таблиц и юзердаты, просто они не используются, а могли бы, в качестве метатаблиц по умолчанию.

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

Когда есть много арифметики с таблицами (причем исключительно с массивами, {a,b,c} без ключей, с целочисленными индексами, размером 2,3,4), написанный сто раз вот этот vec() начинает немного напрягать и хочется куда-нибудь его убрать в одно место (во всех смыслах)

Про {1,2,3,4,5}[3] просто пример, вместо циферок могут быть и буковки. Ну пусть надо взять один элемент из константного массива с магическими циферками который нигде более не встречается, по некоторому индексу, обязательно для него создавать отдельную переменную?
И мне совсем не сложно взять в дополнительные скобочки. Просто непонятно почему t = {1,2,3} и t[k] равносильно ({1,2,3})[k], а не {1,2,3}[k].
А у строк нельзя менять метатаблицу (средствами Lua), вроде бы. Так что было бы разумно не копировать вообще никакой ссылки. Просто если в рантайме происходит обращение к методу строки, то использовать заранее известную одну-единственную метатаблицу для всех строк. И никаких проблем со сборкой мусора.

Много арифметика с таблицами? Насколько я помню, создание таблицы в Lua — это дорогое удовольствие само по себе, потому что связано с выделением памяти. Для сравнения, создание локальной переменной или элемента в существующей таблице обычно не потребляет (новой) памяти. Это так, на заметку. Если оптимизация не критична, то это всё не важно.

Вместо vec({1,2,3}) можно писать vec{1,2,3} — это эквивалентная запись. Не знаю, были ли вы в курсе, но так можно делать. А ещё можно старую-добрую функцию с аргументами — vec(1,2,3), тоже убирает лишнюю пару скобок, но логика слегка меняется. И если так много векторов, то сделайте их в качестве параметров, тогда не нужно пересоздавать их каждый раз.
То есть local A = vec{a,b,c} а потом fn_sum(A,B). Как-то так.
Кстати, если их реально много, то вместо vec может лучше просто v.
Мне сложно судить, возможно я не прав и по-другому действительно нельзя.

Про последнее нечего сказать. Объяснений у меня нет, но багом это не назовешь, и это реально странная ситуация использования языка, имхо. Единственное, можно через вызов функции убрать скобки:
fn{1,2,3}[3]
Это уже можно. Даже можно изменить таблицу, а не просто её возвращать. Но я бы при написании скрипта всё равно поставил скобки для очевидности:
(fn{1,2,3})[3]
Саму таблицу из луа поправить можно:
getmetatable("").__call = function() print(«qwe») end
(«asd»)()
опять эти лишние скобки :)

Вот для однообразия хочется точно так же с метатаблицей по умолчанию для таблиц. Чтобы пока для конкретной таблицы метатаблица не задана, использовалась одна дефолтная метатаблица. и пусть её так как для строк нельзя поменять из луа.
getmetatable(???DEFAULT_TABLE???).__add =… и все новые созданные таблицы будут уметь в арифметику без дополнительных указаний для каждой отдельно.

Это совсем не принципиальная проблема, и даже не проблема вообще, конечно можно сделать конструкторы для каждой таблицы, даже из одной буквы, или использовать функции вместо операторов, но если эти костыли можно было бы куда-то спрятать средствами языка, было бы красивее.
Очень не хватает в lua изолированных функций, которые бы не могли поменять глобальное состояние. Что бы все переменные были локальные по умолчанию. И для доступа к глобальным или upvalues это описывалось бы явно.
Вот кусок кода демонстрирующий проблему:
a="global"
local b="local"

function problem(_ENV)
    a="fn_a"
    b="fn_b"
end

problem{}
print(_VERSION)
print("a",a)
print("b",b)

--[[output:
Lua 5.3
a       global
b       fn_b
]]
Странный пример вы привели. Использование "_ENV" в качестве аргумента функции это какой-то чит. Считайте, что это запрещенное имя, и проблема исчезнет. Или приведите другой пример.

А вообще проблему изолированности функции можно решить простым запретом создания переменных в глобальном пространстве. То есть где-то в конце скрипта объявляется запрет на запись, после того, как все глобальные переменные и функции уже объявлены, но до того, как основной цикл начнет работать. В принципе создание глобальных переменных всё же будет возможно, но через неудобный способ rawset(_G, name, value) — достаточно явно.
Нет. Нужно именно специальное слово для опередления функции, у которой по умолчанию все переменные локальные. Так что бы доступ за пределы данной функции (если он нужен) описывался явно. В рамках lua 5.3 это сделать невозможно, т.к. это поведение компилятора.
local a=1
b=1
function f1()
  a=2 -- меняет upvalue a
  b=2 -- меняет _G.b
end
function f1a(_ENV)
  a=2 -- меняет upvalue a
  b=2 -- меняет _ENV.b
end
pure_function f2(G)
  a=3 -- локальная переменная внутри f2
  b=3 -- локальная переменная внутри f2
  G.print( G.b ) -- доступ к глобальной b
end
f2(_G)

А то о чем вы говорите это не изолирование это ограничение доступа.
Заголовок спойлера
function const(c)
	return setmetatable({},{__index=c,
		__newindex=function(t,n,v) error "const is read only" end
	})
end

function strict(s)
	return setmetatable({},{
		__index=function(t,n)
			if s[n]==nil then error("no "..n.." defined") end
			return s[n]
		end,
		__newindex=function(t,n,v) 
			if s[n]==nil then error("no "..n.." defined") end
			s[n]=v
		end,
	})
end

c=const { pi=3.14, e=2.71 }
s=strict { a="text" }

print(c.pi)
s.a="text2"
print(s.a)

c.pi=3     -- runtime error "const is read only"
print(s.b) -- runtime error "no b defined"
s.b=1      -- runtime error "no b defined"

тем более что break есть, a continue почему-то нет
Вопросов нет. Просто передайте огромное спасибо за создание этого прекрасного языка. И отдельное спасибо за оператор goto!
Спасибо за то, что первый индекс в таблице — 1!
Главный вопрос заключается в поддержке многопоточности.
Когда автор планирует её добавить?
А сам язык достаточно красив, чтобы не придираться к мелочам в синтаксисе.
Это же легковесный встраиваемый язык, в нем вероятно никогда не будет многопоточности, потому что она в нем либо не нужна (95%), либо обеспечивается приложеним (4.9%), либо добавляется модулем lanes.
На нем пишут сложные игры, потому что к таким играм потом легко писать модификации, а это означает развитие игры за счет комьюнити и повышение ее ценности.

За lanes спасибо, изучу вопрос. Не думал, что всё так просто. Возможно, есть подвох.
Ну, игры обычно пишут не на самом Lua, а на каком-нибудь движке поддерживающим скриптование на нем. Например, есть неплохой легковесный Love2d. В нем и поддержка многопоточности есть, правда с ограничением — поток создается из строки кода, поэтому для подсветки синтаксиса ее нужно выносить в отдельный файл.

Если нужно писать веб-приложения (хотя можно и любые другие), то есть Luvit. В нем тоже есть свои механизмы для мультипоточности, поудобней чем в Love2d.
Вопрос автору: «Как Вы думаете, почему Lua так хорошо выстрелил в качестве языка для написания видеоигр (фреймворки Defold, Corona SDK, Love2d и многие)?»
Я бы выделил 3 причины:
1) Простота. Реально, в отличие от какого-нибудь C# и уж тем более C++, этот язык учится за 15 минут.
2) Хеш-таблицы везде нативно! Это очень удобно для написания игровой логики, в отличие от других языков. О них даже не нужно думать.
3) Поддержка модификаций. На самом деле это побочный эффект, но очень удачный. Так как сама игра на Lua, то её легко изменять, причём любую её часть, поэтому мододелы могут реализовать даже самые смелые идеи. Встраиваемость языка дала ему популярность, так что он знаком игрокам, это тоже фактор.

И это всё перевешивает даже явный недостаток — скорость. Lua примерно в 200 раз медленнее, чем C++. Я бы добавил ещё однопоточность, но выше подсказали, что проблема вроде решаема.
Тут есть два момента:
Момент первый — если хочется скорости, можно задействовать способ, рассмотренный в статье habr.com/ru/post/113804 Если же хочется увеличить скорость именно в Lua, то следует обратить внимание на раздел Lua Performance Tips www.lua.org/gems
Второй момент проистекает из первого. Азы Lua можно усвоить за пятнадцать минут из листовки tylerneylon.com/a/learn-lua Но не стоит ограничиваться только лишь ею. И тогда, может быть, количество пустого флейма и холиваров вокруг этого замечательного языка значительно уменьшится.
Достаточно просто взять LuaJIT, и скорость взлетит в небеса, морочиться с FFI не обязательно, тем более если самая тяжелая часть лежит в C-коде. Минус в том, что LuaJIT остановился на поддерже Lua 5.1 и ряда фичек с 5.2, но не сказать что это прям критично. Возможно, в форке RaptorJIT это даже пофиксят со временем.
Полное интервью с Роберто вы сможете прочитать в одной из ближайших публикаций.


Не подскажете, есть ли интервью в открытом доступе?
Мы сейчас согласовываем текстовую версию. Дело оказалось небыстрое. Как только выложим — сюда дам ссылку.
Здравствуйте. Есть какие-то новости? Тоже хотел бы подписаться на апдейты по сабжу.
Спасибо огромное, интересно почитать, что нового в Lua и вообще!
Sign up to leave a comment.