Artigo Java Magazine 62 - Closures em Java

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

Artigo da Revista Java Magazine Edição 62.

Esse artigo faz parte da revista Java Magazine edição 62. Clique aqui para ler todos os artigos desta edição

Closures em Java

Propostas de novo recurso trazem muita discussão

Saiba o que são closures e conheça as diferentes propostas para inclusão do recurso na linguagem Java e o que isso pode significar para o futuro da plataforma

De que se trata o artigo:

O que são closures, como funcionam as três principais propostas para adição de closures à linguagem Java e um resumo da discussão sobre o assunto. O artigo mostra como instalar os protótipos de cada proposta e escrever código com closures em Java.

 

Para que serve:

Para apresentar o leitor a um possível novo recurso da linguagem de programação Java, permitindo assim, que forme uma opinião mais bem fundamentada sobre o assunto.

 

Em que situação o tema é útil:

Caso o recurso de closures venha a ser incluído na linguagem Java ou o leitor necessite usá-lo em outra linguagem de programação que já o possua.

 

Closure é um conceito de linguagens de programação proveniente das linguagens funcionais que também é presente em muitas linguagens orientadas a objetos (e, portanto, imperativas), como Smalltalk, Groovy, Ruby, Python e Scala.

Nos últimos dois anos se discute a adição de closures à linguagem Java. Dado o grande impacto que isso teria na linguagem – por uns julgado positivo, por outros negativo – muito se tem discutido nas conferências, blogs e portais sobre Java se o recurso deveria ser realmente adicionado e, em caso positivo, qual seria a melhor forma de fazê-lo.

Tanta discussão gerou três propostas principais para adição de closures, conhecidas pelas siglas CICE+ARM, FCM e BGGA. Uma delas, a BGGA, já é disponível experimentalmente em builds do OpenJDK. Neste artigo, apresentaremos o que são closures, as três propostas para sua adição à linguagem Java e um resumo da polêmica em torno do assunto.

Ainda que a disponibilidade de uma nova versão do Java incorporando closures seja um plano futuro e incerto, esperamos que esta discussão seja desde já proveitosa para qualquer leitor interessado em se aprofundar no paradigma de Orientação a Objetos – ou mesmo na linguagem Java, cujas inner classes já implementam uma forma restrita de closure.

O que são closures?

Segundo o FOLDOC (veja Links), closure é uma estrutura de dados que contém uma expressão e amarrações[1] de variáveis. Já a Wikipedia a define como uma função que é avaliada em um ambiente contendo uma ou mais variáveis amarradas. As definições mais gerais tratam qualquer elemento que possua um ambiente de variáveis fechado (daí o nome “closures”) que seja um cidadão de primeira classe (veja o quadro “Cidadãos de primeira classe”) como closures. Neste sentido, objetos Java e ponteiros para função em C poderiam ser chamados de closures.

 

Cidadãos de primeira classe

No contexto de linguagens de programação, “cidadãos de primeira” classe são entidades da linguagem que podem ser utilizadas sem restrições, ou seja, podem ser expressas como literais, armazenadas em variáveis, passadas como parâmetros de procedimentos / funções, retornadas como resultados, criadas dinamicamente, etc.

Por exemplo, em Java, métodos não podem ser passados como parâmetros, exceto com o uso de reflexão. Já em C é possível passar ponteiros para funções, porém não é possível criar ou modificar funções em tempo de execução. Neste caso, dizemos que funções de C e métodos Java são cidadãos de segunda classe. Já em FORTRAN 66, strings não podem ser armazenadas em variáveis (realmente não há como).

O termo original em inglês é “first class citizens”, também encontrado na literatura como first class “objects” (objetos), “values” (valores) ou “entities” (entidades).

 

Na prática, e em termos mais simples (talvez até simplista), closures são blocos de código (conjunto de expressões) que podem acessar variáveis do seu escopo e que podem ser criados dinamicamente, armazenados em variáveis e passados como parâmetros. A Listagem 1 traz um exemplo bem simples de uso de closures na linguagem Groovy.

Nos exemplos de código, onde são mostradas closures em várias linguagens ou variantes de closures, destacaremos em negrito todas as closures; e em alguns casos outros elementos de linguagem relacionados ao suporte de closures.

Listagem 1. Exemplos de uso de closures em Groovy.

def clos = { println "Olá!" }  // Definindo a closure e armazenando-a

clos()                         // Invocando a closure

executaClosure(clos)           // Passando como parâmetro

def executaClosure(closure) {

  closure()                    // Invocando a closure passada

}

 

Neste exemplo, uma closure que imprime “Olá!” na tela é definida e armazenada na variável clos. Quando esta variável é chamada como se fosse um método (clos()), o código definido no bloco é executado. A closure pode ser passada como parâmetro para o método executaClosure() e executada dentro do mesmo, imprimindo a mesma mensagem. Outro exemplo, desta vez com passagem de parâmetros e com amarração de variáveis, é mostrado na Listagem 2.

 

Listagem 2. Exemplo de closures com passagem de parâmetros e com amarração de variáveis em Groovy.

def soma = { a, b -> a + b } 

def resultado = soma(7, 5)

println resultado             // Imprime 12

def dobroResultado = { println resultado * 2 }

dobroResultado()              // Imprime 24

resultado++

dobroResultado()              // Imprime 26

 

É interessante notar que a closure armazenada na variável dobroResultado faz referência à uma variável definida fora da closure (no caso, resultado), e que, ao alterar o valor desta variável, o valor impresso com a invocação da closure também muda.

Um pouco de história

Na década de 50, pesquisadores do MIT (Massachusetts Institute of Technology, nos EUA) criaram a linguagem de programação funcional Lisp. Um dos recursos desta linguagem era o das expressões lambda. A palavra-chave lambda pode ser usada para criar uma expressão que funciona como uma função anônima, podendo ser atribuída a uma variável ou passada como parâmetro e invocada posteriormente.

Na década de 70, surge Scheme, um dialeto de Lisp que fazia amarração estática em vez de amarração dinâmica, que vinha sendo feita até então em outros dialetos Lisp (veja o quadro “Amarração estática x dinâmica”). As expressões lambda, portanto, passaram a fazer referência a variáveis definidas nos escopos externos à definição da expressão. Dizia-se, então, que avaliar uma expressão lambda com amarração estática produzia um fechamento (“closure”) em cima destas variáveis. Para diferenciar das linguagens com amarração dinâmica, as expressões lambda com amarração estática se tornaram conhecidas como closures.

 

Amarração estática x dinâmica

Amarração estática e dinâmica são duas formas diferentes de se atribuir (amarrar) um valor a uma variável. Para explicar a diferença, considere o seguinte trecho de código em uma linguagem fictícia com sintaxe similar a Java:

"

A exibição deste artigo foi interrompida :(
Este post está disponível para assinantes MVP

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?