1) А что вам важнее, изящество или скорость?
1.а) Во-первых, изящнее использовать встроенную функцию ipairs, которая как раз интерирует индексный массив:
lines = {"sdss", "vfbf"}
for i, line in ipairs(lines) do
print(line)
end
Это изящнее, чем просто обращение по индексу, потому что исчезает строка создания переменной line, она задаётся в самом цикле. Однако с точки зрения производительности такой способ медленнее, потому что конструкции языка быстрее, чем обращение к функциям, даже встроенным. Так что если у вас миллиарды строк, то лучше ваш вариант, хоть он и менее изящен.
1.б) Во-вторых, в вашем примере создаётся переменная line глобально. Это не ошибка, но может привести к ошибке в будущем, если код будет сложный. Поэтому делать так совсем не изящно. Лучше писать так:
local line = lines[i]
Это создаст локальную переменную внутри цикла. Она не будет доступна вне цикла. А если есть одноименная глобальная переменная, то с ней ничего не произойдет. Везде, где только можно, лучше использовать слово local, оно ограничивает область видимости переменной текущим блоком (и вложенными блоками).
Кстати, массив lines тоже желательно задавать через local, если ваш скрипт не рассчитан на несколько файлов и общее глобальное пространство имен между ними. Дело в том, что такие локально-глобальные переменные в пределах файла чуть быстрее, чем классические глобальные.
2) nil выводит потому, что строки в lua не являются итерируемыми объектами, в отличие от строк в javascript, например. То есть строка является объектом, поэтому обращение к свойству [j] не является синтаксической ошибкой, но свойства такого у строки нет, поэтому line[j] возвращает nil.
Обращение к символу в Lua происходит через функцию подстроки:
line:sub[j,j]
То есть мы буквально вырезаем подстроку с позиции j до позиции j, это и есть один символ.
Опять же, красиво создавать локальные переменные, чтобы читателю вашего кода было понятно, что происходит, а потом их использовать. Желательно с комментариями. Например, так:
local c = line:sub[j,j] --Получаем символ с номером j
print(c) --Выводим символ
3) Ну и, наконец, если вам не важна скорость и производительность совсем, а под изяществом вы понимаете как можно более короткую (и/или сложную для понимания) запись кода, то вам подойдёт что-то вроде этого:
Примерlines = {
"sdss",
"vfbf",
}
for i,line in ipairs(lines) do
for c in line:gmatch"." do
print(c)
end
end
Пример 2lines = {
"sdss",
"vfbf",
}
for i,line in ipairs(lines) do
line:gsub(".",function(c)
print(c)
end)
end
Ведь в Lua использовать в качестве итератора любую функцию, кроме pairs и ipairs, очень необычно, не всем понятно, зато "изящно" (если это можно так назвать). Передавать функции в качестве аргументов другой функции - приём также чуть сложнее, чем просто цикл. Ну и регулярные выражения, само собой разумеется, отдельная сложная тема. Тем более, что в Lua регулярки немного иначе устроены, то есть ещё +10% к сложности.