Buscar

lua_doc

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 20 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Estudo sobre a linguagem de programação Lua*
Bruno Lopes Dalmazo1, Francisco Tiago Avelar1
1Curso de Ciência da Computação – Universidade Federal de Santa Maria (UFSM) – 
Santa Maria, RS – Brasil
{dalmazo, avelar}@inf.ufsm.br
Resumo. Este trabalho apresenta funcionalidades da linguagem brasileira de  
programacão Lua através de uma abordagem simples e informativa. Noções  
gerais de histórico demonstram seu propósito e seus domínios de aplicação  
exemplificam a aceitação do trabalho perante os outros países. Além disso,  
detalhes mais específicos são explicados de modo a apresentar ao profissional  
de   computação   a   grande   facilidade   de   programação   sob   a   abordagem  
envolvendo os conceitos de linguagens de programação.
1. História do surgimento da linguagem
A Petrobrás,  parceira  da  TeCGraf,  grupo de Tecnologia  em Computação gráfica  da 
PUC­RJ,   formado  pelos  professores  Roberto   Ierusalimschy,  Waldemar  Celes   e  Luiz 
Henrique Figueiredo, necessitava traçar um perfil de um poço de petróleo. Durante uma 
perfuração,   junto   com   a   broca,   vários   sensores   descem   em   conjunto,   para   que   os 
geólogos acompanhem o processo. Estes sensores recebem as informações à medida que 
o poço é perfurado. 
Os valores capturados pelos sensores eram colocados em um gráfico na tela do 
computador, com dados diversos, como temperatura, condutividade do material naquela 
profundidade,   resistência   e   pressão.  Os   programas   coletam   estas   informações   e   as 
manipulam para que o gráfico seja montado. Contudo, existem vários fatores complexos 
de configuração que o geólogo pode desejar visualizar. Às vezes, é  preciso ver uma 
coluna do lado da outra; outras; há necessidade de verificar outro tipo de informação, 
mudar a cor ou a escala. A complexidade de realizar esse trabalhado era grande com o 
uso de uma única interface gráfica, pois sempre fica faltando algum detalhe. 
Sendo assim, quando o geólogo necessitava de mais comandos, era obrigado a 
contatar os desenvolvedores da aplicação para que o software fosse alterado ou para que 
fosse criado um novo programa, enviando em seguida para a plataforma. Desta forma 
foi   criado  o  Lua,   para   colocar   um  final   para   esse   problema.  Com esta   linguagem, 
alguém   que   tenha   uma   pequena   formação   técnica   pode   fazer,   ele   mesmo,   essa 
configuração. A linguagem é simples o suficiente para que a pessoa possa modificar e 
* Trabalho Conceitos de Linguagem de Programação (ELC1007) – primeiro semestre 2007.
adaptar   às   suas   necessidades.   Assim,   o   programa   é   um   pouco   de   linguagem   de 
programação C, que cria a parte gráfica, e um pouco de Lua, que pode estar gravada em 
um arquivo texto, encarregado de dizer para o C como as informações são apresentadas.
2. Domínios de aplicação
A linguagem de programação Lua possui grande uso no domínio corporativo voltado 
para   o   mercado   de   jogos   de   computadores   [WoW]   e   consoles   de   video­game 
[Psychonauts].   Além   disso,   é   bastante   empregada   em   aplicações   Web   e   no 
desenvolvimento de ferramentas para auxiliar a pesquisa científica,  como a Biologia 
Molecular [GUPPY]. 
Lua foi projetada para estender aplicações, sendo freqüentemente utilizada como 
uma linguagem de propósito geral. Dessa forma, diversos casos de uso podem ter Lua 
como   parte   da   implementação   de   uma   solução,   seja   para   o   domínio   empresarial, 
científico   e   industrial.  A   comunidade  de  desenvolvimento   em  linguagem Lua  é   de 
domínio geral. Assim, qualquer interessado pode ter acesso a documentação e o código­
fonte da implementação da linguagem, pois Lua é software livre de código aberto. 
Demais exemplos de uso da linguagem Lua de forma a descrever seus domínios 
de aplicação podem ser vistos da Internet, através do website oficial, nas referências 
finais deste trabalho.
3. Variáveis e tipos de dados
As variáveis globais de Lua não precisam ser declaradas. Assim, é possível escrever o 
comando 
a = 2.3 
sem necessidade prévia de declarar a variável global a. Uma característica fundamental 
de Lua é que as variáveis não têm tipo: os tipos estão associados aos dados armazenados 
na variável. Assim, o código acima armazena em  a  um dado do tipo numérico, com 
valor 2.3, enquanto, após o comando 
a = "Linguagem Lua" 
a variável a passa a armazenar um dado do tipo cadeia de caracteres (string). 
Os dados em Lua podem ser de oito tipos básicos: nil, lógico, number, string, 
function, userdata, thread e table.
3.1. Tipo nil
O tipo  nil  representa o valor indefinido. Todas as variáveis ainda não inicializadas 
assumem o valor nil. Assim, se o código: 
a = b 
for encontrado antes de qualquer atribuição à variável  b, então esta é assumida como 
contendo   o   valor  nil,   significando   que  a  também   passa   a   armazenar  nil, 
independentemente do valor anteriormente armazenado em a. A palavra reservada nil 
pode ser usada na programação para expressar o valor do tipo nil. Com isto, pode­se 
escrever: 
a = nil 
que atribui o valor nil à variável a (a partir deste ponto, é como se a variável a ainda 
não tivesse sido atribuída). 
Pode­se testar se uma variável foi inicializada comparando o seu valor com nil: 
a == nil
3.2. Tipo lógico
O  tipo   lógico,   também conhecido  como   tipo  booleano,  pode  assumir   somente  dois 
valores: verdadeiro (true) ou falso (false).
3.3. Tipo number
O  tipo  number  representa   valores   numéricos.   Lua   não   faz   distinção   entre   valores 
numéricos com valores inteiros e reais. Todos os valores numéricos são tratados como 
sendo do tipo number. Assim, o código 
a = 4 
b = 4.0 
c = 0.4e1 
d = 40e­1 
armazena o valor numérico quatro nas variáveis a, b, c e d.
3.4. Tipo string
O tipo  string  representa cadeia de  caracteres.  Uma cadeia  de caracateres  em Lua é 
definida por uma seqüência de caracteres delimitadas por aspas simples (' ') ou duplas (" 
"). A seqüência de caracteres deve estar numa mesma linha de código. 
Por simplicidade, quando a cadeia de caracteres é delimitada por aspas duplas, 
pode­se   usar   aspas   simples   no   seu   conteúdo,   sem   necessidade   de   tratá­las   como 
seqüências   de   escape.  Entretanto,   para   reproduzir   na   cadeia   de   caracteres   as   aspas 
usadas  como   delimitadoras,  é  necessário  usar  os   caracteres  de  escape.  Assim,   são 
válidas e  equivalentes as seguintes atribuições: 
s = "Marca d'agua" 
s = 'Marca d\'agua' 
Colchetes duplos ([[ ]]) também podem ser utilizados como delimitadores de 
strings.   Diferentemente   dos   delimitadores   aspas   simples   e   aspas   duplas,   esse 
delimitador não interpreta sequências de escape e tolera que a string tenha “quebras de 
linhas” e pode conter strings com delimitadores aninhados. Exemplo: 
s = [[Esse é um texto que 
atravessa 
mais de uma linha
e contém uma string aninhada: [[aninhada]] no final !]]
3.5. Tipo function
Funções em Lua são consideradas valores de primeira classe. Isto significa que funções 
podem ser armazenadas em variáveis, passadas como parâmetros para outras funções, 
ou retornadas como resultados. A definição de uma função equivale a atribuir a uma 
variável global o valor do código que executa a função (ver definição de escopo). Esta 
variável global passa a armazenar um dado do tipo  function.  Assim, adiantando um 
pouco a sintaxe de definição de funções, o trecho ilustrativo de código abaixo armazena 
na variável func1 um valor do tipo function: 
function func1 (...) 
... 
end 
que pode posteriormente ser executada através de uma chamada de função: 
func1(...) 
3.6. Tipo userdata
O tipo  userdata permite armazenar numa variável de Lua um ponteiro qualquer de C. 
Este tipo corresponde ao tipo void* de C e somente pode ser atribuído ou comparado 
para   igualdade   a   outro   valor   de  mesmo   tipo   em  Lua.  Este   tipo   é  muito  útil   para 
programadoresde aplicação que fazem a ligação Lua­C, mas não é  manipulado por 
usuários que programam somente em Lua, pois não é possível criar dados deste tipo 
diretamente em Lua.
O   próposito   de   oferecer   esse   tipo   de   dado   na   linguagem   Lua   é   oferecer 
integração com as demais linguagens, pois assim mantem o ideal de ser uma linguagem 
simples, facilmente estensível e de propósito geral.
3.7. Tipo thread
O   tipo  thread  representa   diferentes   fluxos   de   execução,   sendo   utilizado   para 
implementar  subrotinas   (coroutines).  Não confundir  Lua  threads  com as  do sistema 
operacional. Lua suporta subrotinas em todos os sistemas, mesmo os que não possuem 
suporte a threads. 
A   forma   especial   de  coroutines  na   linguagem  Lua   também   é   chamada   de 
multithreadings  colaborativas,   representando   um   fluxo   independente   de   execução. 
Entretanto,   diferentemente   das  threads  em   sistemas  multithreads,   uma  coroutine 
somente encerra sua execução através da chamada explícita de função de entrega (yield  
function). 
Simplesmente   invocando  coroutine.create,   uma  coroutine  é   criada 
retornado um objeto do tipo thread de manipulação. A função não inicia sua execução 
nesse ponto de desenvolvimento do programa. 
Quando   chamado   pela   primeira   vez  coroutine.resume,   passando   o 
argumento do tipo thread retornado por coroutine.create, a coroutine inicia sua 
execução na primeira linha da função principal. Os argumentos adicionais são passados 
juntamente com o tipo thread para a função da coroutine. Depois de iniciar a execução, 
permanece até terminar ou ocorre uma interrupção yield. 
Há somente duas maneiras de uma coroutine encerrar: normalmente, quando sua 
função principal retorna (explicitamente ou implicitamente após a última instrução); ou 
incorretamente,   se  há   presença  de  erros.  No  primeiro  caso,  coroutine.create 
retorna true, além das variáveis retornadas pela função principal de coroutine. No caso 
de erros, coroutine.resume retorna false mais uma mensagem de erro. 
Ocorre  yield  através   da   chamada   explícita   de  coroutine.yield. 
Acontecendo   isso,   o   correspondente  coroutine.resume  retorna   imediatamente, 
mesmo se um yield ocorre dentro de função aninhada, ou seja, não na função principal, 
mas na função diretamente ou indiretamente chamada pela função principal. No caso de 
yield,  coroutine.resume  também retorna  true,  além dos valores  passados para 
coroutine.yield. Na próxima vez que a mesma coroutine é retomada, a execução 
continua   do   ponto   onde   ocorreu  yield,   com   a   chamada   de  coroutine.yield 
retornando quaisquer argumentos extras passados por coroutine.resume.
function func_secundaria (a) 
   print("func_secundaria", a) 
   return coroutine.yield(2 * a) 
end 
    
co_rotina= coroutine.create( function (a,b) 
   print("co_rotina", a, b) 
   local r = func_secundaria(a + 1) 
   print("co_rotina", r) 
   local r, s = coroutine.yield(a + b, a­b) 
   print("co_rotina", r, s) 
   return b, "fim" 
end) 
            
print("principal", coroutine.resume(co_rotina, 1, 10)) 
print("principal", coroutine.resume(co_rotina, “r”)) 
print("principal", coroutine.resume(co_rotina, “x”, “y”)) 
print("principal", coroutine.resume(co_rotina, “x”, “y”)) 
A saída da execucão do programa é representado abaixo:
co_rotina       1       10 
func_sec        2 
principal       true    4 
co_rotina       r 
principal       true    11      ­9 
co_rotina       x       y 
principal       true    10      fim 
principal       false   cannot resume dead coroutine 
3.8. Tipo table
O tipo  table  (tabela) é o tipo mais expressivo da linguagem. Este tipo implementa os 
chamados vetores associativos, que permitem indexação por valores de qualquer outro 
tipo, com exceção do tipo  nil. As tabelas em Lua permitem a construção de vetores 
convencionais, listas e records numa mesma estrutura. Tabelas devem ser explicitamente 
criadas. Adiantando a sintaxe de criação de uma tabela, o código 
a = { } 
cria uma tabela vazia e armazena em a este valor. Novos campos podem ser adicionados 
posteriormente a esta tabela.
A partir  de  table,  é  possível  implementar diversas estruturas de dados,  como 
arrays comuns, tabela de símbolos, conjuntos, registros, grafos, árvores, etc.
4. Comandos de controle
Lua possui os mecanismos usuais para controle de fluxo. Estes controladores agrupam 
diversos comandos em blocos que podem ou não serem executados uma ou mais vezes. 
Lua também permite a declaração de variáveis locais. Estas variáveis deixam de existir 
ao final do bloco onde foram declaradas.
4.1. Estrutura If
O comando de decisão básico de Lua é o if, sendo representado por uma das formas 
abaixo:
if expr then 
bloco 
end 
ou 
if expr then 
bloco1... 
else 
bloco2... 
end 
ou ainda 
if expr1 then 
bloco1 
elseif expr2 then 
bloco2 
... 
elseif expr N then 
bloco N 
else 
bloco N+1 
end
Na primeira forma, o bloco de comandos representado por bloco é executado se 
a  expressão  expr  produzir um valor diferente de  nil. Na segunda forma,  bloco2 
será executado se expr produzir o valor nil. Caso contrário, bloco1 será executado. 
A terceira forma ilustra a possibilidade de tomada de decisão entre diversas alternativas 
usando­se o comando if­then­elseif­then­...­else­end. No código ilustrado,  bloco1  é 
executado   se  expr1  produzir   um valor   verdadeiro   (diferente   de  nil),  bloco2  é 
executado   de  expr2  for   verdadeiro,   ...,   e  bloco N+1  é   executado   se   todas   as 
expressões forem falsas (i.e., iguais a nil).
4.2. Estrutura while (tomadas de decisão no início)
A instrução while permite que a tomada de decisão (se os comandos do laço devem ou 
não ser executados) seja feita no início do bloco. Sua forma geral é: 
while expr do 
bloco 
end 
isto é, enquanto a expressão expr produzir um valor verdadeiro (diferente de nil), os 
comandos do bloco são executados. Para exemplificar, considere o código abaixo que 
calcula   o   fatorial   de   um  número   (assumido   como   inteiro   positivo)   armazenado   na 
variável n: 
f = 1  ­­ valor do fatorial 
i = n  ­­ controle do laço 
while i > 0 do 
f = f * i 
i = i – 1 
end 
Ao final da execução do código acima, f armazena o valor do fatorial de n e i 
armazena o valor zero (condição de fim de execução do laço).
4.3. Estrutura repeat (tomadas de decisão no final)
A construção de um laço com tomada de decisão no fim pode ser feita através do 
comando repeat. Sua forma geral é: 
repeat 
bloco 
until expr 
Nesta construção, o bloco de comandos é executado pelo menos uma vez (pois o 
teste  de   decisão   só   ocorre   no   final   do   laço)   e   é   repetido   até   se   alcançar   o   valor 
verdadeiro para a expressão. O mesmo exemplo de cálculo de fatorial pode ser escrito: 
f = 1  ­­ valor do fatorial 
i = 1  ­­ controle do laço 
repeat 
f = f * i 
i = i + 1 
until i > n
4.4. Estrutura for
A   estrutura  for  apresenta   duas   formas:   uma   numérica   e   outra   genérica.  A   forma 
numérica   repete   as   instruções   do   bloco   numa  progressão   aritmética   definida   como 
primeiro valor a atribuição numérica exp1 em var, com limite máximo exp2 numa 
razão exp3. No caso da ausência exp3, o incremento padrão é unitário.
for var = exp1, exp2 [, exp3] do
bloco 
end
A   declaração   do  for  genérico   trabalha   sobre   funções,   conhecidos   como 
iteradores.  A cada  iteração, a  função de  iteração é  chamada para produzir  um novo 
valor, encerrando quando nil é encontrado. O laço genérico é representado de acordo 
com a sintaxe
for namelist in explist do 
bloco 
end
ou de forma mais representativa,
for var_1, ∙∙∙, var_n in explist do
bloco
end
Conforme foi definido na seção 3.8, a estrutura table é um tipo primitivo em Lua 
com comportamento dinâmico. O exemplo abaixo implementa um percurso numa tabela 
para procurar um determinado valor na estrutura,retornando verdadeiro ou falso como 
resultado na busca de um determinado valor no interior da tabela. Através do código, é 
simples de perceber como os valores inicializados da tabela representam tipos distintos 
de dados.
­­ devo declarar explicitamente uma tabela local 
local tabela = {} 
function func() 
   ­­ funcao func() eh uma variavel 
   ­­ que sera inserida na tabela 
end 
tabela = {5, false, 3.14, func, nil, "texto"} 
function existe_valor(valor) 
    for k, v in pairs(tabela) do    ­­ 'for' genérico
        if v == valor then 
            return true 
        end 
    end 
    return false 
end 
parametro = "texto" ­­ apenas atribui o que será procurado 
if( existe_valor(parametro) ) then 
io.write( tostring(parametro).." 'encontrado." ) 
else 
io.write( tostring(parametro).." ' NAO encontrado." ) 
end 
io.write("\n")
5. Subprogramas (funções)
Conforme foi dito na seção 3.5, a linguagem Lua trata funções como valores de primeira 
classe. Quando definimos uma função em Lua, o armazenando é feito na variável global 
cujo nome corresponde ao nome da função o código “de máquina” interno da função, 
que pode posteriormente ser executado através de chamadas para a função.
Funções em Lua podem ser definidas em qualquer lugar do ambiente global. A 
forma básica para definição de funções é 
function nome ( [lista­de­parâmetros] ) 
bloco de comandos 
end
onde nome representa a variável global que armazenará a função. Pode­se fornecer uma 
lista de parâmetros que são tratados como variáveis  locais  da função e  inicializados 
pelos valores dos argumentos na chamada da função. 
A chamada da função segue a forma básica 
nome ( [lista­de­argumentos] )
isto é, o nome da função é seguido de abre e fecha parênteses, que pode ou não conter 
uma lista de argumentos.  Se nome não for uma variável que armazena um valor de 
função (i.e., do tipo function), Lua reporta um erro de execução (TAG METHODS). Se 
presente, a lista de argumentos é avaliada antes da chamada da função. Posteriormente, 
os valores dos argumentos são ajustados para a atribuição dos parâmetros seguindo uma 
regra de atribuição múltipla na qual os parâmetros recebem os valores dos argumentos. 
Lua passa parâmetros por valor. Isto quer dizer que quando se altera o valor de 
um   parâmetro   dentro   de   uma   função,   altera­se   apenas   o   valor   da   variável   local 
correspondente ao parâmetro. O valor da variável passada como argumento na chamada 
da função permanece inalterado. 
Funções em Lua podem retornar zero, um ou mais valores através do comando 
return.  A  possibilidade  de   retorno  múltiplo   evita   a   necessidade  de  passagem de 
parâmetros por referência. Quando, durante a execução de uma função, encontra­se o 
comando return, a execução da função é terminada e o controle volta para o ponto 
imediatamente posterior à chamada da função. O comando return pode vir seguido 
de uma lista de expressões; sua forma geral é
return [lista­de­expressões]
Por razões sintáticas, o comando return deve sempre ser o último comando de 
um bloco de comandos. Deste modo, evita­se a ocorrência de comandos inalcançáveis 
(tendo em vista que comandos após return nunca serão executados). Se return não 
for o último comando do bloco, Lua reporta um erro de sintaxe. 
Os valores retornados por uma função são ajustados para a atribuição na linha 
que faz a chamada. Para exemplificar, supõe­se uma função que incrementa os valores 
de um ponto cartesiano (x, y): 
function translada (x, y, dx, dy) 
return x+dx, y+dy 
end 
Considera­se, agora, que a chamada da função é feita por: 
a, b = translada(20, 30, 1, 2) 
Assim,  a  recebe o valor 21 (= 20 + 1) e  b  recebe o valor 32 (= 30 + 2). Se a 
chamada fosse 
a = translada(20, 30, 1, 2) 
então o segundo valor retornado seria desprezado, e  a  receberia o valor 21. Por outro 
lado, a atribuição: 
a, b, c = translada(20, 30, 1, 2) 
faria a = 21, b = 32 e c = nil.
É importante notar que uma chamada de função que retorna múltiplos valores 
não pode estar no meio de uma lista de expressões. Por razões de ajustes de valores em 
atribuições múltiplas, se uma função estiver sendo chamada no meio de uma lista de 
expressões, só se considera o primeiro valor retornado. Para exemplificar, duas situações 
sutilmente  diferentes  são analisadas;  considera­se  inicialmente a  chamada de  função 
abaixo: 
a, b, c = 10, translada(20, 30, 1, 2) 
que faz com que  a  receba  o valor  10,  b  o  valor  21 e  c  o  valor  32.  Neste  caso,  o 
funcionamento  é   o   esperado,   tendo  em vista   que  a   chamada  da   função  é   a  última 
expressão numa lista de expressões. No entanto, se o código fosse 
a, b, c = translada(20, 30, 1, 2), 10 
então teria­se resultados incorretos, já que a chamada da função está no meio de  uma 
lista de expressões. Conforme mencionado, independentemente do número de valores 
retornados pela função, considera­se apenas o primeiro (no caso, o valor 21). 
O valor 32 retornado pela função é perdido durante o ajuste. Assim, teríamos 
como resultado o valor 21 armazenado em a e o valor 10 armazenado em b. A variável 
c, então, receberia o valor nil, pois não se tem outra expressão após a constante 10. 
É possível definir funções em Lua que aceitem número variável de argumentos. 
Para tanto é necessário acrescentar à lista de argumentos da definição a indicação “...” 
(três pontos seguidos). Uma função definida dessa forma não faz ajuste do número de 
parâmetros em relação ao número de argumentos. Ao invés disso, quando a função é 
chamada os argumentos extras são colocados em um parâmetro implícito de nome arg. 
Esse parâmetro é   sempre  inicializado como uma tabela,  onde o campo  n  contém o 
número   de   argumentos   extras   e   os   campos   1,   2,   ...   os   valores   dos   argumentos, 
seqüencialmente. 
Para exemplificar, duas diferentes definições de funções são apresentadas: 
function f(a, b) end 
function g(a, b, ...) end 
Os seguintes  mapeamentos  de  argumentos  a  parâmetros   seriam efetuados  na 
chamada dessas funções:
Chamada Parâmetros
f(3) a = 3, b = nil
f(3, 4) a = 3, b = 4
f(3, 4, 5) a = 3, b = 4
g(3) a = 3, b = nil, arg = { n = 0 }
g(3, 4) a = 3, b = 4, arg = { n = 0 }
g(3, 4, 5, 8) a = 3, b = 4, arg = { 5, 8; n = 2 }
6. Subprogramas sobrecarregados e genéricos.
A  linguagem  Lua   não   apresenta   declaração   formal   para   tipos   de   dados,   conforme 
mencionado na seção 3. Dessa forma, subprogramas possuem comportamento genérico 
quando a aceitabilidade de dados de entrada e retorno de valores. Por outro lado, em se 
tratando de sobrecarga de operadores  na  linguagem Lua, uma estrutura  interessante, 
chamada metatable, foi criada para permitir maior flexibilidade no desenvolvimento de 
programas.
Elemento presente em qualquer variável na linguagem Lua, um metatable é uma 
table  comum cuja função é definir o comportamento do valor original perante certas 
operações. É possível efetuar diversas alterações do comportamento das operações sobre 
o valor através de ajustes dos campos específicos na metatable. Por exemplo, quando um 
valor   não­numérico   é   operando   de   uma   adição,   Lua   verifica   a   função   no   campo 
"__add" na sua metatable. Ao encontrar alguma, ocorre a invocação dessa função para 
desempenhar a adição. É possível consultar eventos de um metatable e os metamétodos 
de qualquer valor através da função  getmetatable.  No caso anterior,  o evento é 
"add" para o metamétodo da função que efetua a adição. No caso de substituir um 
metatable em tabelas, passa a ser usado a função setmetatable. 
Tables e userdata possuem metatables individuais (apesar que múltiplas tabelas 
e  userdata  compartilham   suas  metatables),   ao   passo   que   todos   os   outros   tipos 
compartilham um único metatable por tipo. Desse modo, há uma única metatable para 
todos os numbers, uma para todas as strings, etc. 
Um  metatable  pode  controlar  o   comportamento  de  um objetoem operações 
aritméticas,   comparações,   concatenação,   cardinalidade,   indexação,   etc.  Além  disso, 
pode definir uma função para ser chamada quando um userdata  é coletado para lixo. 
Para cada uma dessas operações, Lua associa uma chave específica denominado evento. 
Ao desempenhar uma dessas operações sobre um valor, Lua verifica caso esse valor 
possui   uma  metatable  com   o   evento   correspondente.   Em   caso   afirmativo,   o   valor 
associado com aquela chave (o metamétodo) controla como a linguagem irá efetuar a 
operação. 
Cada operação é identifidada pelo nome correspondente. A chave é uma string 
com o nome prefixado de duas sublinhas, '__', por exemplo. Desse modo, a chave para a 
operação de adição é a string "__add". 
A função getbinhandler abaixo define como Lua escolhe um manipulador 
para uma operação de binária. Primeiramente, o primeiro operando é verificado, caso 
seu tipo não define um manipulador para a operação, o segundo operando é analisado. 
function getbinhandler (op1, op2, event) 
return metatable(op1)[event] or metatable(op2)[event] 
end
A  tabela   segue com a   representação  string  dos  operadores  em Lua que  possuem a 
capacidade de sobrecarga através de metatables.
Nome Descrição Símbolo
“add” adição +
“sub” subtração ­
“mul” multiplicação *
“div” divisão /
“mod” resto da divisão %
“pow” exponenciação ^
“unm” unário ­
“concat” concatenação ..
“len” cardinalidade #
“eq” equivalência ==
“lt”1 menor a <
“le”2 menor ou igual a <=
“index” acesso indexado table[key]
“newindex” atribuição de indexação table[key] = 
value
“call” chamada de valor ausente
O exemplo abaixo representa o uso de  metatable para o operador de adição de 
forma a ser sobrecarregado através da atribuição de um manipulador m.
1 a>b é equivalente a  b<a
2 a>=b é equivalente a  b<=a. Notar que, na ausência do metamétodo “le”, Lua tenta “lt”, assumindo 
que a<=b é equivalente a not(b < a)
 function evento_add (op1, op2) 
   local o1, o2 = tonumber(op1), tonumber(op2) 
   if o1 and o2 then  ­­ ambos operandos são numéricos? 
     return o1 + o2   ­­ '+' primitiva 'add' 
   else  ­­ pelo menos um não é numérico
     local m = getbinhandler(op1, op2, "__add") 
     if m then 
       ­­ invoca o manipulador com os dois operandos
       return m(op1, op2) 
     else  ­­ não há manipulador: comportamento padrão
       error(∙∙∙) 
     end 
   end 
 end
7. Escopo (regras de visibilidade)
Lua   é   uma   linguagem   com   escopo   léxico   de   variáveis,   iniciando   na   primeira 
especificação após as declarações e permanece até o final do bloco mais interno que 
inclui a declaração. Considerando o exemplo abaixo, fica simples de deduzir.
x = 10 ­­ variável global
do ­­ novo bloco
local x = x ­­ novo 'x', com valor 10 
print(x) ­­ imprime 10
x = x+1 
do ­­ outro bloco
local x = x+1 ­­ outro 'x' 
print(x) ­­ imprime 12 
end 
print(x) ­­ imprime 11 
end 
print(x) ­­ imprime 10  (variável global)
Lua permite que se defina explicitamente variáveis de escopo local. A declaração 
de uma variável local pode ocorrer em qualquer lugar dentro de um bloco de comandos, 
e seu escopo termina quando termina o bloco no qual foi declarada. A declaração de 
uma   variável   local   com   mesmo   nome   de   uma   variável   global   obscurece 
temporariamente (i.e., dentro do bloco da declaração local) o acesso à variável global. 
Quando o programador escrever o nome da variável, estará se referindo à variável local. 
Variáveis   locais  podem ser   inicializadas  na declaração seguindo a  sintaxe de 
atribuições. Para exemplificar, considere o código abaixo: 
a = 2  ­­ variável global igual a 2 
if a > 0 then 
   local b = a  ­­ variável local 'b' com atribuição 2
   a = a + 1 ­­ incrementa a variável global 'a'
­­ de uma unidade 
   local a = b  ­­ declara­se uma variável local 'a'
­­ que recebe o valor de 'b' 
   print(a)  ­­ a refere­se a variável local, 
­­ logo imprime o valor 2 
end  ­­ fim do bloco e do escopo de 
­­ 'a' e 'b' locais 
print(a)  ­­ 'a' refere­se à variável global, logo
­­ imprime o valor 3 
Pode­se ainda declarar e inicializar várias variáveis locais num mesmo comando: 
local a, b, c = 2, 5+6, ­3 
Neste   caso,  a  recebe   2,  b  recebe   11   e  c  recebe   ­3.  Variáveis   locais   não 
inicializadas assumem o valor nil.
8. Acesso a ambientes não locais
Na linguagem Lua, funções são variáveis locais tratadas como qualquer outro tipo de 
dado. Desse modo, quando ocorre o caso de funções estarem definidas no interior de 
outras, um mecanismo para acessar variáveis em diferentes níveis de programa criou o 
conceito de encerramento de variáveis e funções não­globais. Nas subseções seguintes, 
ambos os casos são verificados.
8.1. Closures (“encerramentos”)
Quando uma função é escrita no interior de outra, a função incluída passa a ter acesso 
completo a   todas  as  variáveis   locais  da   função  detentora;   funcionalidade  conhecida 
como escopo léxico. Embora pareça simples, às vezes não é tão óbvia quanto seja. 
O   pequeno   código   abaixo   ilustra   o   conceito   simples   envolvendo  closures. 
Suponha uma lista de estudantes e as notas ambos armazenados numa table. O objetivo 
é ordenar a lista de nomes de acordo com as notas em ordem decrescente. 
nomes = {"Pablo", "Paula", "Mariana"} 
notas = {Mariana = 10, Paula = 7, Pablo = 8} 
table.sort(nomes, function (n1, n2) 
   return notas[n1] > notas[n2]    ­­ compara as notas 
end) 
Agora, suponha que o código que contém a função que desempenha a tarefa de 
ordenação dos nomes de alunos  através da nota maior até a nota menor:
function ordena_por_nota(nomes, notas) 
   table.sort(nomes, function (n1, n2) 
      return notas[n1] > notas[n2]    ­­ compara as notas 
   end) 
end 
O exemplo demonstra que a função anônima interna a  sort  acessa o parâmetro 
notas, o qual é local (parâmetro formal) na função ordena_por_nota. No interior 
na função anônima,  notas  não é nem uma variável global e tanto como não é uma 
variável local. O conceito envolvido é denominado variável local externa, ou upvalue3. 
Qual o diferencial dessa idéia? O motivo é devido às funções serem variáveis de 
primeira classe. Considere o código: 
function novo_contador() 
   local i = 0 
   return function()   ­­ função anônima 
         i = i + 1 
         return i 
      end 
end 
c1 = novo_contador() 
print( c1() )  ­­> 1 
print( c1() )  ­­> 2 
A função anônima utiliza um upvalue, i, para manter seu contador. Entretanto, 
na ocasião de invocação da função anônima,  i está fora de escopo, pois a função que 
criou   a   variável   (novo_contador)   encerrou   com   o   retorno.   Apesar   disso,   Lua 
gerencia a situação corretamente através do conceito de  closures. Em outras palavras, 
uma  closure é uma função incluindo todas as características para acessar  upvalues  de 
forma correta. Ao invocar  novo_contador  novamente, uma nova variável local  i 
será criada, assim como uma nova closure, atuando sobre a nova variável: 
c2 = novo_contador() 
print( c2() )  ­­> 1 
print( c1() )  ­­> 3 
print( c2() )  ­­> 2 
Como se pode concluir, c1 e c2 são diferentes closures sobre a mesma função e 
cada ação atua sob instanciação independente da variável local i. Mais especificamente, 
todo valor em Lua é  uma  closure,  não uma função.  Por si  só,   função é  apenas  um 
protótipo para closures. 
3 O termo "upvalue" é um tanto enganoso, pois notas é uma variável, não um valor. Entretanto, esse 
termo possui raízes históricas da linguagem Lua e também é uma forma de abreviatura para "variável 
local externa".
Através do mecanismo de  closures, programas em Lua incorporam técnicas de 
programação personalizáveis, como uso de callbacks, muito úteis para aplicativos GUI. 
Outro uso de closures  justifica a grande flexibilidade de Lua, pois funções são 
variáveis   regulares   e   podem   ser   facilmente   redefinidas.   Por   exemplo,   suponha   que 
queremos redefinir a função seno para operarcom ângulos em graus ao invés de arcos 
em radianos. Essa nova função deve converter seu argumento e então chamar a função 
seno original para efetuar o trabalho real. Considere o código: 
seno_velho = math.sin 
math.sin = function (x) 
   return seno_velho(x * math.pi/180) 
end 
Um exemplo de uso da função está abaixo :
do 
   local seno_velho = math.sin 
   local l = math.pi/180 
   math.sin = function (x) 
      return seno_velho(x * l) 
   end 
end 
A idéia foi manter a versão antiga numa variável privada. O único caminho e 
acesso é através da nova versão. 
A partir  do  conceito  de   redefinição  de   funções,  é  possível  utilizar  a  mesma 
característica   para   criar   ambientes   seguros,   também   conhecidos   como  sandboxes 
("caixas de areia"). Segurança é essencial quando há execução de código não confiável, 
como um trecho de programa recebido através da Internet por um servidor. Por exemplo, 
para restringir acesso aos arquivos por um programa "desconhecido", a função open, da 
biblioteca io, pode ser redefinida utilizando closures: 
do 
   local velho_open = io.open 
   io.open = function (nome_arq, modo) 
      if access_OK(nome_arq, modo) then 
         return velho_open(nome_arq, modo) 
      else 
         return nil, "acesso negado" 
      end 
   end 
end 
O que torna esse exemplo interessante é que, após a redefinição, não há mais um 
modo do programa invocar o open irrestrito, exceto através da nova e restrita versão. O 
resultado   foi  manter   a   versão   insegura   como   uma   variável   privada   numa  closure, 
inacessível ao exterior. Com essa facilidade, é possível construir sandboxes até mesmo 
em   Lua,   aproveitando   o   benefício   usual:   flexibilidade.   Dessa   forma,   ao   invés   de 
soluções   únicas   gerais,   Lua   oferece   meta­mecanismos   para   que   possa   adequar   o 
ambiente para necessidades específicas de segurança.
8.2. Funções não­globais.
Uma evidente conseqüência das funções de primeira classe é que é possível armazenar 
funções não somente em variáveis globais, mas também em tables e em variáveis locais. 
Quando uma função é armazenada numa variável local, a função será local, ou seja, 
restrita a um dado escopo. 
Tal  definição é  particularmente  útil  para  pacotes:  Lua manipula cada  chunk4 
como  uma   função,   uma  chunk  pode  declarar   funções   locais,   as   quais   são   somente 
visíveis no interior de um chunk. O escopo léxico garante que outras funções no pacote 
podem usar essas funções locais: 
local f = function (...) 
   ... 
end 
    
local g = function (...)  ­­ igual a local funcion g(...) 
   ... 
   f()   ­­ função externa 'f()' visível aqui 
   ... 
end 
Uma questão importante ocorre na definição de recursividade em funções locais. 
A abordagem primária abaixo não irá funcionar: 
local fatorial = function (n) 
   if n == 0 then return 1 
   else return n * fatorial(n­1)   ­­ ocorre erro 
   end 
end 
Quando   Lua   compila   a   chamada   fatorial  fatorial(n­1),   no   corpo   da 
função, o fatorial local ainda não foi definido. Portanto, a expressão do código onde 
ocorre erro invoca a global  fatorial,  não a  local.  Para resolver esse problema, é 
necessário definir a variável local e então criar a função: 
4 Cada porção de código em Lua pode ser chamado de chunk, tal como um arquivo ou uma única linha 
de comando. Mais especificamente, um chunk é simplesmente uma seqüência de declarações. Veja 
nas referências para saber mais.
local fatorial 
fatorial = function (n) 
   if n == 0 then return 1 
      else return n*fatorial(n­1) 
   end 
end 
Agora fatorial no interior da função faz referência a variável local. Seu valor não 
importa quando a função é definida, pois em tempo de execução, fatorial já possui o 
valor correto. Uma maneira expansiva para funções locais possui uma forma alternativa 
para uso de recursividade: 
local function fatorial (n) 
   if n == 0 then return 1 
   else return n * fatorial(n ­ 1) 
   end 
end 
Por outro lado, esse recurso não funciona quando ocorre recursividade de forma 
indireta. Nesses casos, é preciso usar a declaração explícita:
local f, g    ­­ declaração explícita 
    
function g () 
   ...  f() ... 
end 
    
function f () 
   ...  g() ... 
end 
9. Conclusões
O estudo envolvendo conceitos de linguagens de programação representa o requisito 
básico para o compreendimento das entidades e elementos de linguagens de forma a 
diferenciar os diversos própositos da criação de linguagens, visto que não existe uma 
soluçãoo universalmente utilizada que atenda todos os requisitos no desenvolvimento de 
sistemas  em computação.  Em  termos de  evolução,  países  desenvolvidos   iniciaram a 
pesquisa na criação de linguagens de programação, regendo técnicas e paradigmas para 
desenvolvimento de programas. 
Resultados   consagrados   na   criação   de   linguagens   de   programação   são 
fundamentados na capacidade simplificada no uso e expressão dos mecanismos para 
desenvolvimento de programas, além de ferramentas envolvendo o apoio para correção 
de erros  (debug) e  interfaces  integradas de desenvolvimento,  nos quais são recursos 
essenciais para qualquer linguagem moderna para programação.
A linguagem de programação Lua demonstrou possuir grandes características 
reunidas   de   soluções   existentes   no   desenvolvimento   de   linguagens   e   sustena   os 
paradigmas de programação estudados formalmente em Ciência da Computação. Além 
disso, incorpora funcionalidades próprias, como a alta flexibilidade no desenvolvimento 
de código, gerência automática de memória e a integração com demais sistemas. Em 
outras   palavras,   a   linguagem   não   recria   os  mecanismos   existentes   das   linguagens 
consagradas de programação. A aceitação de Lua por diversos programadores ao redor 
do mundo está na simplificidade de código aliado a magnitude para implementação de 
programas.
O presente trabalho comprova que pesquisadores e profissionais brasileiros em 
Ciência da Computação possuem grande capacidade na criação de linguagens e sistemas 
de forma a contribuir significativamente para facilitar a solução de muitos problemas do 
mundo moderno, oferecendo meios facilitadores de expressão entre Homem e máquina, 
além de técnicas que ofereçam desempenho aceitável e clareza no tratamento de erros.
Referências
WoW – World of Warcraft ­ http://www.worldofwarcraft.com/
Psychonauts ­ Double Fine Productions ­  http://www.doublefine.com/
GUPPY ­ genetic sequence visualization . Computational Biology Research Center, 
AIST Tokyo. http://staff.aist.go.jp/yutaka.ueno/guppy/
Aplicações da linguagem Lua: http://www.lua.org/uses.html
Página oficial da Linguagem Lua: http://www.lua.org/
Livro on­line: http://www.lua.org/pil/
Manual do programador: http://www.lua.org/manual/5.1/
Lua chunks: http://www.lua.org/pil/1.1.html
Artigo que recebeu o primeiro prêmio (categoria tecnologia) no II Prêmio Compaq 
de Pesquisa e Desenvolvimento em Ciência da Computação em 1997: 
http://www.lua.org/spe.html
Artigo envolvendo corotinas em Lua:
http://www.inf.puc­rio.br/~roberto/docs/corosblp.pdf
Página geral de papers sobre Lua:
http://www.lua.org/papers.html
	1.História do surgimento da linguagem
	2.Domínios de aplicação
	3.Variáveis e tipos de dados
	3.1.Tipo nil
	3.2.Tipo lógico
	3.3.Tipo number
	3.4.Tipo string
	3.5.Tipo function
	3.6.Tipo userdata
	3.7.Tipo thread
	3.8.Tipo table
	4.Comandos de controle
	4.1.Estrutura If
	4.2.Estrutura while (tomadas de decisão no início)
	4.3.Estrutura repeat (tomadas de decisão no final)
	4.4.Estrutura for
	5.Subprogramas (funções)
	6.Subprogramas sobrecarregados e genéricos.
	7.Escopo (regras de visibilidade)
	8.Acesso a ambientes não locais
	8.1.Closures (“encerramentos”)
	8.2.Funções não-globais.
	9.Conclusões

Outros materiais