Lucas Teixeira

@lucastex

Arquivo para a tag ‘Scala’

Não tenha medo das closures

com 13 comentários

Você tem medo das closures? Já vi muita gente dizer que closures são perigosas e trazê-las a tona seria como acordar um monstro adormecido (o medonho GOTO – veja uma ótima definição neste link).

Não eu não concordo, closures só querem o seu bem, eis a razão.

Bom, uma closure nada mais é que um trecho de código! Mas o que difere este bloco de instruções chamado closure de um método? A grande diferença neste caso, é que as closures são um pouco mais flexíveis que os métodos, e por sua vez podem até ser passadas como parâmetro na chamada de outras funções, ou seja, podem ser atribuídas a uma variável.

Em java não temos closures nativas na linguagem, e uma das formas de tentar alcançar o objetivo é através do uso de classes anônimas, o que particularmente não me agrada muito, pela sujeira que fica no código.

Em um primeiro exemplo, mais simples, segue como definir uma closure, associá-la a uma variável e depois executá-la. (exemplo em groovy).

def c = {
    println "Testando o uso de uma closure"
}
c.call()

Este é um exemplo simples, onde a frase acima será impressa no console.

Para incrementarmos um pouco, podemos fazer com que nossa closure receba um parâmetro para usá-lo dentro da execução, além de criar um método que faça o uso dela. O exemplo abaixo mostra isto.

//definição da closure para dizer oi
def ola = { nome ->
    println "E ai ${nome}, tudo bom?"
}

//definição da closure para dizer tchau
def tchau = { nome ->
    println "To indo ${nome}, ate a proxima!"
}

//criação do método que fará o uso da closure
void falar(Closure c, String paraQuem) {
    c.call(paraQuem)
}

//invoke do método com as closures de parametro
//note que a closure é passada como se fosse uma variável qualquer
falar(ola, "Fulano")
falar(tchau, "Ciclano")

Mas uma das maiores vantagens que eu enxergo nas closures, é a possibilidade de definição delas em runtime. Isso mesmo, conforme você programa, pode criar uma nova closure e chamar uma função que precise dela! Vemos isso em ruby e groovy com frequência para métodos onde iteramos listas e mapas.

Por exemplo, as listas e arrays em groovy possuem um método each que recebe uma closure como parâmetro, esta closure define o que será feito com cada um dos items da lista/array em questão. O exemplo abaixo mostra a praticidade de se fazer a definição da closure inline, ou seja, sem criar uma variável para ela antes.

Em groovy

//groovy
def lista = ["Ferrari", "RBR", "STR", "Brawn", "Renault", "Williams"]
lista.each { equipe ->
    println "A equipe ${equipe} correu na #F1 em 2009"
}

Em ruby

#ruby
lista = ["Ferrari", "RBR", "STR", "Brawn", "Renault", "Williams"]
lista.each { |equipe|
    puts "A equipe #{equipe} correu na #F1 em 2009"
}

Em scala

//scala
val teams = List("Ferrari", "RBR", "STR", "Brawn", "Renault", "Williams")
teams foreach {
   team => printf("A equipe %s correu na #F1 em 2009", team)
}

Dá pra perceber que a closure foi criada já no momento em que ela foi usada. Desta maneira, além de fácil, um código muito mais limpo e fácil de ser entendido.

Acredite, closures são suas amigas, e estão aqui pra te ajudar, então aproveite!

Ahh, e fica a dica de sempre: Ler a documentação:

Closures em Groovy (wiki) (groovydoc) (definição formal)
Closures (Proc) em Ruby (doc) (wiki)
Closures em Scala (wiki)

Written by Lucas Teixeira

October 21st, 2009 at 11:55 am

Postado em Groovy, Ruby, Scala

Com as tags , , , ,

Get Adobe Flash playerPlugin by wpburn.com wordpress themes