Closures
Capture estado.
Closures é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que é uma closure?
Uma closure é uma função que captura variáveis do escopo ao redor em que foi definida. Ela mantém uma referência a essas variáveis, continuando a acessá-las mesmo depois que esse escopo termina.
object Main {
def main(args: Array[String]): Unit = {
val factor = 3
val multiply = (x: Int) => x * factor
println(multiply(5))
}
}Capturando uma variável livre
Em x => x * factor, x é um parâmetro, mas factor é uma variável livre obtida do escopo externo. A função mantém uma referência a ela.
object Main {
def main(args: Array[String]): Unit = {
val greeting = "Hello"
val greet = (name: String) => s"$greeting, $name!"
println(greet("Ann"))
println(greet("Bob"))
}
}As closures sobrevivem ao escopo
Quando uma função retorna uma closure, as variáveis capturadas permanecem vivas enquanto a closure existir, mesmo que a função que a definiu já tenha terminado.
object Main {
def makeAdder(n: Int): Int => Int = x => x + n
def main(args: Array[String]): Unit = {
val add10 = makeAdder(10)
val add100 = makeAdder(100)
println(add10(5))
println(add100(5))
}
}Cada closure tem sua própria captura
Chamar uma fábrica de funções duas vezes produz duas closures independentes, cada uma lembrando seu próprio valor capturado.
object Main {
def prefixer(p: String): String => String = s => p + s
def main(args: Array[String]): Unit = {
val withDr = prefixer("Dr. ")
val withMr = prefixer("Mr. ")
println(withDr("Smith"))
println(withMr("Jones"))
}
}Capturando estado mutável
Uma closure pode capturar uma var e tanto lê-la quanto atualizá-la. Isso permite que uma closure mantenha estado entre chamadas, como um contador.
object Main {
def main(args: Array[String]): Unit = {
var count = 0
val increment = () => { count += 1; count }
println(increment())
println(increment())
println(increment())
}
}Uma fábrica de contadores
Combine as ideias: uma função que retorna uma closure capturando sua própria var privada fornece um contador encapsulado e independente.
object Main {
def counter(): () => Int = {
var n = 0
() => { n += 1; n }
}
def main(args: Array[String]): Unit = {
val c1 = counter()
val c2 = counter()
println(c1())
println(c1())
println(c2())
}
}As closures capturam referências, não cópias
Uma closure captura a variável, não uma cópia instantânea. Se a var capturada mudar depois que a closure for criada, a closure verá o novo valor.
object Main {
def main(args: Array[String]): Unit = {
var msg = "first"
val show = () => println(msg)
show()
msg = "second"
show()
}
}Prefira capturar val
Capturar uma val imutável evita surpresas: o valor capturado nunca muda, então a closure se comporta de maneira previsível. Prefira a captura de val em código funcional.
object Main {
def main(args: Array[String]): Unit = {
val taxRate = 0.2
val withTax = (price: Double) => price * (1 + taxRate)
println(withTax(100))
}
}Closures com métodos de coleções
Lambdas passadas para map, filter etc. são closures sempre que fazem referência a variáveis externas. Isso é extremamente comum no uso cotidiano de Scala.
object Main {
def main(args: Array[String]): Unit = {
val threshold = 3
val nums = List(1, 2, 3, 4, 5)
val big = nums.filter(_ > threshold)
println(big)
}
}Uma armadilha de captura em laços
Em Scala, a variável de um laço for é uma nova associação a cada iteração, portanto as closures capturam valores distintos. Isso evita um erro clássico presente em algumas outras linguagens.
object Main {
def main(args: Array[String]): Unit = {
val fns = for (i <- 1 to 3) yield () => i
println(fns.map(f => f()))
}
}Closures encapsulam comportamento + dados
Uma closure combina comportamento (o corpo da função) com dados (as variáveis capturadas). Essa é uma alternativa simples a um pequeno objeto com um método.
object Main {
def discounter(rate: Double): Double => Double = price => price * (1 - rate)
def main(args: Array[String]): Unit = {
val sale = discounter(0.25)
println(sale(80))
println(sale(200))
}
}Verificação rápida
O que uma closure captura do escopo ao seu redor?
Recapitulação
Você aprendeu sobre closures:
- Uma closure captura variáveis livres do escopo que a envolve
- As variáveis capturadas sobrevivem à função que as definiu
- Cada instância de closure tem seu próprio estado capturado
- As closures capturam referências, portanto as capturas mutáveis podem mudar
- Lambdas usadas com
map/filtersão closures comuns no dia a dia
Aprenda Scala com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 39
- Aulas
- 143
Perguntas Frequentes
A aula “Closures” é grátis?
Sim — o texto completo de “Closures” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Closures”?
Capture estado. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Closures”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.