Aprenda Lua em 15 minutos



-- Dois hifens começam um comentário de uma linha.

--[[
Adicionando dois "[" e "]" cria um
comentário de múltiplas linhas
--]]

----------------------------------------------------
-- 1. Variáveis e controle de fluxo.
----------------------------------------------------

num = 42 -- Todos os números são Double.
-- Não se espante, 64-bit Doubles têm 52 bits para armazenar valores inteiros exatos;
-- precisão da máquina não é um problema para inteiros que precisam de menos de 52 bits.

s = 'aspas simples' -- Strings imutáveis, como Python
t = "aspas duplas também funcionam"
u = [[ Chaves duplas
começam e terminam
uma string de múltiplas linhas. ]]
t = nil -- Indefine t; Lua tem coleta de lixo.

-- Blocos são denotados com palavras-chave como do/end:
while num < 50 do
num = num + 1 -- Não há os operadores ++ ou +=.
end

-- Condições If
if num > 40 then
print('acima de 40')
elseif s ~= 'aspas simples' then -- ~= significa diferente (não igual).
-- Igualdade é ==, como em Python; ok para strings.
io.write('não é maior que 40\n') -- Padrão de saída (stdout).
else
-- Variáveis são globais por padrão.
istoEhGlobal = 5 -- Camel Case é comum.

-- Como fazer uma variável local
local linha = io.read() -- Lê a próxima linha de entrada (stdin).

-- Concatenação de string usa o operador ..
print('O inverno está chegando, ' .. linha)
end

-- Variáveis indefinidas retornam nil.
-- Isto não é um erro:
nada = valorDesconhecido -- Agora nada = nil.

valorBooleano = false

-- Apenas nil e false são falsos; 0 e "" são true (verdadeiros)!
if not valorBooleano then print('falso') end

-- 'or' e 'and' funcionam em sistema de short-circuiting.
-- É semelhante ao operador a?b:c em C/JS:
resposta = valorBooleano and 'sim' or 'não' --> não

minhaSoma = 0
for i = 1, 100 do -- O alcance/raio/intervalo inclui ambos os fins [1-100]
minhaSoma = minhaSoma + 1
end

-- Use "100, 1, -1" como um alcance/raio/intervalo em ordem decrescente:
suaSoma = 0
for j = 100, 1, -1 do suaSoma = suaSoma + j end

-- Em geral, o alcance/raio/intervalo é Começo, Final[, Etapa].

-- Outra construção de loop:
repeat
print("Para o alto e avante")
num = num - 1
until num == 0

----------------------------------------------------
-- 2. Funções.
----------------------------------------------------

function Fibonacci(n)
if n < 2 then return 1 end
return Fibonacci(n - 2) + Fibonacci(n - 1)
end

-- Funções anônimas e "Closures" funcionam:
function adicionador(x)
-- A função retornada é criada quando adicionar é chamado
-- e lembra o valor de x
return function(y) return x + y end
end
a1 = adicionador(9)
a2 = adicionador(36)
print(a1(16)) --> 25
print(a2(64)) --> 100

-- Todos os retornos, chamadas de função e atribuições funcionam
-- como listas que talvez possam estar incompatíveis em comprimento/tamanho.
-- Variáveis incompatíveis são nil;
-- Valores incompatíveis são descartadas.

x, y, z = 1, 2, 3, 4
-- Agora x = 1, y = 2, z = 3, e 4 foi jogado fora.

function barra(a, b, c)
print(a, b, c)
return 4, 8, 16, 23, 42
end

x, y = barra("teste") --> Imprime "teste nil nil"
-- Agora x = 4, y = 8, valores de 15 até 42 são descartados.

-- Funções são primeira classe, podem ser locais ou globais.
-- Ambas são as mesmas:
function f(x) return x * x end
f = function(x) return x * x end

-- E também:
local function g(x) return math.sin(x) end
local g; g = function(x) return math.sin(x) end
-- A declaração 'local g' cria uma referência de/em g.

-- A propósito, funções trigonométricas trabalham em radiano.

-- Chamadas com um parâmetro não precisam de parênteses:
print 'hello' -- Funciona

----------------------------------------------------
-- 3. Tabelas.
----------------------------------------------------

-- Tabelas = Única estrutura de dados compostos em Lua; São arrays associativas.
-- Similar às arrays de PHP ou objetos de JS.
-- São como dicts (dicionários) em Python que podem ser usados, também, como listas.

-- Usando tabelas como dicionários / mapas:

-- Têm chaves de tipo string como padrão:
t = {chave1 = 'valor1', chave2 = false}

-- Chaves de tipo string usam notação com um ponto '.'
print(t.chave1) -- Imprime 'valor1'.
t.novaChave = {} -- Adiciona um novo par de chave/valor
t.chave2 = nil -- Remove chave2 da tabela.

-- Notação literal para qualquer valor não nulo como chave:
u = {["@!#"] = 'Brasil', [{}] = 1729, [1.41] = 'Órion'}
print(u[1.41]) -- Imprime 'Órion'.

-- Correspondência de chave é basicamente de valor para números e strings, mas por identidade por tabelas.
a = u["@!#"] -- Agora a = 'Brasil'
b = u[{}] -- Espera-se 1729, mas é nil:
-- b = nil porque a pesquisa falhou.
-- Falhou porque a chave usada não é o mesmo objeto que a usada para armazenar o valor original.
-- Então strings e números são chaves mais portáveis.

-- A chamada de uma função que contém apenas um parâmetro, tal sendo uma tabela, não precisa de parênteses:
function h(x) print(x.chave1) end
h{chave1 = 'Teste1234'} -- Imprime 'Teste1234'.

for chave, valor in pairs(u) do -- Iteração/Repetição de tabela
print(chave, valor)
end

-- _G é uma tabela especial que armazena todas as variáveis globais.
print(_G['_G'] == _G) -- Imprime 'true'.

-- Usando tabelas como listas / arrays:

-- Têm chaves de tipo inteiro como padrão:
v = {'valor1', 'valor2', 1.244, 'internet'}
for i = 1, #v do -- #v é o tamanho de v
print(v[i]) -- Índices começam em 1, não 0.
end
-- Uma 'lista' não é um tipo real. v é apenas uma tabela com
-- consecutivos índices inteiros, tratados como uma lista.

----------------------------------------------------
-- 3.1 Metatabelas e Metamétodos.
----------------------------------------------------

-- Uma tabela pode ter uma metatabela que fornece um comportamento de "operador de sobrecarga".
-- Depois veremos como metatabelas suportam comportamentos como os prototipados em JS.

f1 = {a = 1, b = 2} -- Representa a fração a/b .
f2 = {a = 2, b = 3}

-- Isso daria errado:
-- s = f1 + f2

metaFracao = {}
function metaFracao.__add(f1, f2)
soma = {}
soma.b = f1.b * f2.b
soma.a = f1.a * f2.b + f2.a * f1.b
return soma
end

setmetatable(f1, metaFracao)
setmetatable(f2, metaFracao)

s = f1 + f2 -- Chama __add(f1, f2) na metatabela de f1

-- f1, f2 não têm chaves para suas metatabelas, ao contrário dos protótipos em JS, então
-- podem ser recuperadas usando getmetatable(f1). A metatabela é uma tabela normal com
-- chaves das quais Lua reconhece, como __add.

-- Mas a próxima linha dá erro, uma vez que s não tem metatabela:
-- t = s + s
-- Padrões de "classes" dadas abaixo consertam isso.

-- Um __index numa metatabela sobrecarrega pesquisas com ponto '.':
favoritos = {animal = "Galinha Galinácea", comida = "Nachos"}
meusFavoritos = {comida = "Batata Frita"}
setmetatable(meusFavoritos,{__index = favoritos})
comidoPor = meusFavoritos.animal -- Funciona!

-- Pesquisas diretas com ponto '.' em tabelas que falharem tentarão novamente usando
-- o valor __index da metatabela e seus recursos.

-- Um valor __index pode ser também uma função, function(tabela, chave) para pesquisas mais customizadas.

-- Valores de __index, add, ... são chamados de metamétodos.
-- Todos os metamétodos estão listados abaixo, onde a é uma tabela com o metamétodo.

-- __add(a, b) --> para a + b
-- __sub(a, b) --> para a - b
-- __mul(a, b) --> para a * b
-- __div(a, b) --> para a / b
-- __mod(a, b) --> para a % b
-- __pow(a, b) --> para a ^ b
-- __unm(a) --> para -a
-- __concat(a, b) --> para a .. b
-- __len(a) --> para #a
-- __eq(a, b) --> para a == b
-- __lt(a, b) --> para a < b
-- __le(a, b) --> para a <= b
-- __index(a, b) --> Função ou tabela --> para a.b
-- __newindex(a, b, c) --> para a.b = c
-- __call(a, ...) --> para a(...)

--------------------------------------------------------
-- 3.2 Tabelas como classes e herança.
--------------------------------------------------------

-- Classes não vem embutidas; há formas diferentes de criá-las
-- usando tabelas e metatabelas.

-- Explicação abaixo do código.

planeta = {} -- 1.

function planeta:new(habitavel, celcius) -- 2.
novoObjeto = {vida = habitavel, temperatura = celcius} -- 3.
self.__index = self -- 4.
return setmetatable(novoObjeto, self) -- 5.
end

function planeta:verificarVida() -- 6.
print((not self.vida and "não " or "") .. "sou habitável! ")
end

marte = planeta:new(true, 30) -- 7.
marte:verificarVida() -- 8.

--[[ 1. planeta agirá como uma classe, mas é uma tabela.
2. function nomedatabela:funcao(...) é o mesmo que function nomedatabela.funcao(self, ...)
o : adiciona um primeiro argumento chamado self.
Leia 7 & 8 para ver como self pega seu valor.
3. novoObjeto será uma instância da classe planeta.
4. self = a classe sendo instanciada. Geralmente self = planeta, mas a herança pode alterar isso.
novoObjeto obtém as funções de self quando definimos as metatabelas de novoObjeto
e o __index de self em self.
5. setmetatable retorna seu primeiro argumento.
6. O : funciona como em 2, mas desta vez self será uma instância ao invés de uma classe.
7. O mesmo que planeta.new(planeta), então self = planeta em new().
8. O mesmo que marte.verificarVida(marte); self = marte. ]]

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

-- Exemplo de herança:

estrela = planeta:new(false, 1000) -- 1.

function estrela:calor()
s = self.temperatura .. "°C" -- 2.
print("Minha temperatura é de " .. s)
end

sirius = estrela:new() -- 3.
sirius:calor() -- 4.

--[[ 1. estrela obtém os métodos e variáveis de planeta.
2. self tem uma chave 'temperatura', vinda de new(), veja 3.
3. o mesmo que estrela.new(estrela), e convertido para
planeta.new(estrela) já que estrela não tem nova chave, mas
tem __index = planeta em sua metatabela.
Resultado: a metatabela de sirius é estrela, e estrela.__index = estrela,
então sirius.chave = sirius.chave, estrela.chave, planeta.chave, qualquer tabela
é a primeira com a chave dada.
4. A chave 'calor' se encontra em estrela; é o mesmo que estrela.calor(sirius). ]]

-- Se necessário, uma subclasse de new() é como a base:
function estrela:new()
novoObjeto = {}
-- configure novoObjeto
self.__index = self
return setmetatable(novoObjeto, self)
end

--[[
Criado pelo usuário do Github Tylerneylon (veja oficial https://gist.github.com/tylerneylon/5853042)
Traduzido por Bolodefchoco e publicado por Rikkeshang.

Para quem quer usar, assim como eu, o LUA para desenvolver Dialplan no Asterisk, temos um grupo no telegram, mas é somente para discutir sobre LUA em Dialplan do Asterisk, por favor respeite. Segue o link: https://t.me/asteriskluabr

Divirta-se com Lua (:.
]]

Nenhum comentário

Toda vez que um homem supera os reveses, torna-se mentalmente e espiritualmente mais forte!

Tecnologia do Blogger.