Isto é uma pré-visualização de um tema em Hitskin.com
Instalar o tema • Voltar para a ficha do tema
[Lua] Enum
2 participantes
Página 1 de 1
[Lua] Enum
Enum é uma lista de certa forma uma lista de identificadores que possuem valores numéricos (variam de acordo com a definição do usuário e de linguagem).
Na maioria dos casos o uso é basicamente o seguinte:
Não da pra obter o mesmo resultado em Lua mas a gente pode chegar perto. A representação em Lua para quem ainda não mentalizou seria assim:
Nota-se que temos que definir o valor de cada item manualmente e o resultado final é uma table que pode ser modificada (adicionar ou remover itens por exemplo podem fazer com que o funcionamento do enum se torne inválido).
Nós podemos corrigir esse problema de definir novos valores de uma forma muito simples: usando metatables.
Quando um valor é adicionado a uma table (seja pelo table.insert ou uma atribuição direta: a = b) a função __newindex definida dentro da metatable do objeto é chamada. Para impedir que novos valores sejam adicionados nós sobreescrevemos esta função e liberamos um erro caso ela seja chamada.
Ou seja, se por engano você ou alguém tentar definir um novo campo no enum dessa forma o sistema irá encontrar um erro. Isso não é tudo que podemos fazer, meu objetivo é no final deste post vocẽs consigam declarar enumerações em lua de forma semelhante a linguagens como C (eu disse semelhante >.>)
O primeiro passo pra atingirmos esse objetivo é pararmos de usar diretamente a table para definir os valores do enum. Para isso vamos criar uma função chamada enum e ela retornará uma table com todos os elementos definidos a partir dos parametros recebidos. Seria mais ou menos assim:
Acredito que alguns de vocês já percebeu que tem um problema na nossa implementação, ela não permite atribuir valores aos elementos. Para resolvermos isso, ao inves de recebermos os elementos que farão parte do enum por direto do argumentos, vamos passar eles para uma table.
O código acima com essas modificações é:
Agora que estamos utilizando uma table para passar os elementos podemos mudar um pouco a forma como usamos. Quando o argumento de uma função é passado como um objeto literal de string ou table (desde que apenas um argumento) o uso de parêntesis se torna desnecessário, logo temos o seguinte código:
Para fazer uma parte do trabalho usaremos a função pairs que retorna dois valores (chave e valor) para cada item de uma table. O código descrito seria o seguinte:
Espero que tenham gostado do tutorial, se tiver feedback posso fazer outros posts sobre Lua.
Na maioria dos casos o uso é basicamente o seguinte:
- Código:
enum Abc {
A = 1,
B,
C
}
Abc.A // 1
Abc.B // 2
Abc.C // 3
Não da pra obter o mesmo resultado em Lua mas a gente pode chegar perto. A representação em Lua para quem ainda não mentalizou seria assim:
- Código:
local Abc = {
A = 1,
B = 2,
C = 3
}
print(Abc.A) -- 1
print(Abc.B) -- 2
print(Abc.C) -- 3
Nota-se que temos que definir o valor de cada item manualmente e o resultado final é uma table que pode ser modificada (adicionar ou remover itens por exemplo podem fazer com que o funcionamento do enum se torne inválido).
Nós podemos corrigir esse problema de definir novos valores de uma forma muito simples: usando metatables.
- Código:
local Abc = setmetatable({
A = 1,
B = 2,
C = 3
}, {
__newindex = function()
error('nenhum elemento pode ser adicionado a um enum')
end
})
Abc.X = 4
- Código:
nenhum elemento pode ser adicionado a um enum
Quando um valor é adicionado a uma table (seja pelo table.insert ou uma atribuição direta: a = b) a função __newindex definida dentro da metatable do objeto é chamada. Para impedir que novos valores sejam adicionados nós sobreescrevemos esta função e liberamos um erro caso ela seja chamada.
Ou seja, se por engano você ou alguém tentar definir um novo campo no enum dessa forma o sistema irá encontrar um erro. Isso não é tudo que podemos fazer, meu objetivo é no final deste post vocẽs consigam declarar enumerações em lua de forma semelhante a linguagens como C (eu disse semelhante >.>)
O primeiro passo pra atingirmos esse objetivo é pararmos de usar diretamente a table para definir os valores do enum. Para isso vamos criar uma função chamada enum e ela retornará uma table com todos os elementos definidos a partir dos parametros recebidos. Seria mais ou menos assim:
- Código:
local abc = enum('A', 'B', 'C')
print(abc.A) -- 1
print(abc.B) -- 2
print(abc.C) -- 3
- Código:
function enum(...)
local args, ntable, count = {...}, {}, 1
for i = 1, #args do
ntable[args[i]] = count
count = count + 1
end
return setmetatable(ntable, { __newindex = function()
error('nenhum elemento pode ser adicionado a um enum')
end})
end
Acredito que alguns de vocês já percebeu que tem um problema na nossa implementação, ela não permite atribuir valores aos elementos. Para resolvermos isso, ao inves de recebermos os elementos que farão parte do enum por direto do argumentos, vamos passar eles para uma table.
O código acima com essas modificações é:
- Código:
function enum(otable)
local ntable, count = {}, 1
for i = 1, #otable do
ntable[otable[i]] = count
count = count + 1
end
return setmetatable(ntable, { __newindex = function()
error('nenhum elemento pode ser adicionado a um enum')
end})
end
local abc = enum({'A', 'B', 'C'})
print(abc.A) -- 1
print(abc.B) -- 2
print(abc.C) -- 3
Agora que estamos utilizando uma table para passar os elementos podemos mudar um pouco a forma como usamos. Quando o argumento de uma função é passado como um objeto literal de string ou table (desde que apenas um argumento) o uso de parêntesis se torna desnecessário, logo temos o seguinte código:
- Código:
local abc = enum { 'A', 'B', 'C' }
print(abc.A) -- 1
print(abc.B) -- 2
print(abc.C) -- 3
- Código:
local abc = enum {
'A',
'B',
'C'
}
print(abc.A) -- 1
print(abc.B) -- 2
print(abc.C) -- 3
Para fazer uma parte do trabalho usaremos a função pairs que retorna dois valores (chave e valor) para cada item de uma table. O código descrito seria o seguinte:
- Código:
function enum(otable)
local ntable, count = {}, 1
for key, value in pairs(otable) do
local tk = type(key)
if tk == 'number' then
ntable[value] = count
count = count + 1
elseif tk == 'string' then
ntable[key] = value
else
error('nenhum objeto do tipo "'..tk..'" pode ser usado como elemento de um enum')
end
end
return setmetatable(ntable, { __newindex = function()
error('nenhum elemento pode ser adicionado a um enum')
end})
end
local abc = enum {
'A',
B = 3,
'C'
}
print(abc.A) -- 1
print(abc.B) -- 3
print(abc.C) -- 2
Espero que tenham gostado do tutorial, se tiver feedback posso fazer outros posts sobre Lua.
_________________
Página 1 de 1
Permissões neste sub-fórum
Não podes responder a tópicos