attempt to index local 'self' (a nil value)

132 views
Skip to first unread message

Guilherme Santiago

unread,
Sep 23, 2011, 1:23:48 PM9/23/11
to Lua BR
Olá pessoal, sou um novato em Lua, e eu estou tentando aprender OO em
Lua. Para isso, estou criando uma agenda simples pra praticar, só que
deu esse erro:

attempt to index local 'self' (a nil value)

Eu não entendo o motivo desse erro...
Acontece quando eu chamo alguma função da classe, self:funcao(), só
que funciona de boa quando eu chamo a função dentro da função :new

Elias Barrionovo

unread,
Sep 23, 2011, 4:03:09 PM9/23/11
to lua...@googlegroups.com
2011/9/23 Guilherme Santiago <guilherme....@gmail.com>:

> Olá pessoal, sou um novato em Lua, e eu estou tentando aprender OO em
> Lua. Para isso, estou criando uma agenda simples pra praticar, só que
> deu esse erro:
>
> attempt to index local 'self' (a nil value)

Em geral esse erro acontece por causa da definição da função que não
possui o parâmetro self.
Em geral, você deve definir as funções e usá-las da seguinte forma:
t = {}
function t.foo(self, a)
--faz algo com self e a
end
t.foo(t, 'a') -- precisa passar a tabela como parâmetro.


No entanto, Lua oferece a facilidade sintática ':', que
automaticamente adiciona o self como primeiro parâmetro. O código
anterior é equivalente a:
t = {}
function t:foo(a)
--faz algo com self e a (self é colocado como parâmetro implicitamente).
end
t:foo('a') -- t é passado implicitamente como primeiro parâmetro (para self).

Espero ter ajudado. Abraço!

--
NI!

Guilherme Santiago

unread,
Sep 23, 2011, 4:38:40 PM9/23/11
to Lua BR
O problema acontece quando eu chamo a função. Mas quando eu chamo a
função dentro do :new, ela funciona normalmente, mas quando eu chamo a
função fora do :new, (mas dentro da "classe"), acontece o erro.

Por exemplo:

function Exemplo:new ()
self:exemplo_funcao() -- Acontece de boa
end

function Exemplo:teste ()
self:exemplo_funcao -- Dá o erro
end

Guilherme Santiago

unread,
Sep 23, 2011, 4:40:49 PM9/23/11
to Lua BR
Para dar certo, eu teria que colocar o nome da classe no lugar do
self.

Exemplo:exemplo_funcao()

Ao invés de self:exemplo_funcao()

Elias Barrionovo

unread,
Sep 23, 2011, 4:51:54 PM9/23/11
to lua...@googlegroups.com
2011/9/23 Guilherme Santiago <guilherme....@gmail.com>:

Esse código roda aqui sem problemas além do fato de faltar os
parênteses em 'self:exemplo_funcao'.
Não estou entendendo seu erro.
O 'self' só pode ser chamado de dentro de uma função que foi declarada
com self de parâmetro explicitamente (function bar.foo(self) end) ou
implicitamente com o uso de ':' (function bar:foo() end).

Você teria como colocar aqui a definição da função que dá problema?
--
NI!

Guilherme Santiago

unread,
Sep 23, 2011, 5:04:24 PM9/23/11
to Lua BR
Aqui está o código:



Agenda = {
contatos = { nome = {}, telefone = {}, email = {} }
}
-- new
function Agenda:new()
self:title('-- Menu inicial')
local ops = {'1 - Meus Contatos','2 - Add Contato','3 - Sair'}
local funcoes = {self.meus_contatos,self.add_contato,self.sair}
self:opcoes(ops,funcoes)
end

-- titulo
function Agenda:title (msg)
os.execute('cls') -- Limpa a tela
puts('=',40)
print('-- Agenda desenvolvida em Lua ')
puts('-',40)
print(msg)
puts('=',40)
end

-- define as opções
function Agenda:opcoes (o,funcoes)
-- Imprime as opções
for i=1,#o do
print(o[i])
end
io.write('Digite sua opcao --> ')
local op = tonumber(io.read())
while true do
if contains(o,op) then
break
else
io.write('\nOpcao invalida! Tente novamente --> ')
op = io.read()
end
end
funcoes[op]() -- Executa a função escolhida
end

-- mostrar os contatos
function Agenda:meus_contatos ()
os.execute('cls')
print('Meus contatos...')
-- ... nao terminei ainda
end

-- adicionar novo contato
function Agenda:add_contato ()
os.execute('cls')
print('Add novo contato')
-- ... nao terminei ainda
end

-- Método para sair
function Agenda:sair()
self:title('-- Deseja mesmo sair?') -- erro aqui
local ops = {'1 - Sim, desejo sair!','2 - Nao, desejo voltar!'}
local funcoes = {os.exit,os.exit}
self:opcoes(ops,funcoes) -- erro aqui tbm
end

=========================

Ele dá erro na funcao Agenda:sair(), quando eu chamo o self:title e o
self:opcoes.
Para dar certo, eu teria que substituir o self pelo nome da classe,
que seria Agenda, ficando:

Agenda:title e Agenda:opcoes

Mas quando eu chamo essas mesmas funções dentro da :new, elas
funcionam de boa.

Elias Barrionovo

unread,
Sep 23, 2011, 5:33:39 PM9/23/11
to lua...@googlegroups.com
Descobri o problema.

Quando você chama funcoes[op](), você está executando a função
escolhida sem passar nenhum argumento. Então, na execução da função
escolhida, o parâmetro self é nil e, por isso, dá o erro.
Colocando funcoes[op](self), você passa o valor de self da função
Agenda.opcoes (que, no caso, quando chamada a partir de new, é a
tabela Agenda) para a função escolhida pelo usuário.

Uma nota à parte: em Lua, ao contrário de muitas linguagens OO, o self
não possui nenhum significado especial; você pode chamá-lo do que
quiser e passar qualquer valor. No entanto, convenciona-se (e o
syntatic sugar ':' usa essa convenção) de que, quando se deseja passar
a própria tabela que guarda a função como primeiro parâmetro,
colocamos o nome 'self'.

Espero ter ajudado.
Abs!

--
NI!

Guilherme Santiago

unread,
Sep 23, 2011, 7:25:14 PM9/23/11
to Lua BR
^^ Valeu mesmo pela ajuda Elias, estou muito grato.

Mas agora eu acabei ficando com uma outra dúvida.

Na parte onde eu guardei as funções, tá assim:

local funcoes = {self.meus_contatos,self.add_contato,self.sair}

Para não precisar colocar o self explicitamente, eu troquei o . por :,
ficando assim:

local funcoes = {self:meus_contatos,self:add_contato:self.sair}

Mas ele dá o seguindo erro:

function arguments expected near ','

Abs!

Elias Barrionovo

unread,
Sep 23, 2011, 7:38:52 PM9/23/11
to lua...@googlegroups.com
Quando voce diz "onde eu guardei as funcoes" voce se refere aa lista
de funcoes passada como parametro para Agenda.opcoes ?

Se sim, voce nao pode substituir '.' por ':'. Os dois pontos sao
syntatic sugar para *chamadas* ou *definicoes* de funcoes. Ou seja,
ele coloca um parametro self na definicao da funcao ou joga a tabela
como primeiro argumento na chamada da funcao.

O que voce esta fazendo ali eh passar as funcoes propriamente ditas
(referencia a elas), mas voce nao as esta chamando. Voce so as chama
mais tarde em funcoes[op](self) e, por isso, voce precisa desse self.

Abs!

> --
> Lua BR - http://groups.google.com/group/lua-br
>

--
Sent from my mobile device

NI!

Guilherme Santiago

unread,
Sep 23, 2011, 7:54:59 PM9/23/11
to Lua BR
Entendi. Obrigado pela ajuda :D
Abraços
Reply all
Reply to author
Forward
0 new messages