20
Estudo sobre a linguagem de programação Lua * Bruno Lopes Dalmazo 1 , Francisco Tiago Avelar 1 1 Curso 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.

Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 linguagemA 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.

Page 2: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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çãoA 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 dadosAs 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 

Page 3: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 

Page 4: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 linhae 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 programadores de 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. 

Page 5: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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)             

Page 6: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 controleLua 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 

Page 7: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 

Page 8: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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] dobloco 

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 

Page 9: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 

Page 10: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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) 

Page 11: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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:

Page 12: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

Chamada Parâmetrosf(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 objeto  em 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 

Page 13: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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<a2 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)

Page 14: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

 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 globaldo ­­ novo bloco

local x = x ­­ novo 'x', com valor 10 print(x) ­­ imprime 10x = 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: 

Page 15: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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:

Page 16: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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".

Page 17: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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 operar com â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 

Page 18: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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.

Page 19: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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.

Page 20: Estudo sobre a linguagem de programa o LuaEstudo sobre a linguagem de programação Lua* Bruno Lopes Dalmazo1, Francisco Tiago Avelar1 1Curso de Ciência da Computação – Universidade

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ênciasWoW – 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.htmlPá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.htmlArtigo 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.htmlArtigo envolvendo corotinas em Lua:http://www.inf.puc­rio.br/~roberto/docs/corosblp.pdfPágina geral de papers sobre Lua:http://www.lua.org/papers.html