Kotlin: como passar uma função como parâmetro? Entendendo com exemplos
\n\nOlá, amigo! Se você já escreveu em Kotlin e se perguntou: "Como passar uma função como parâmetro para outra função?" — você veio ao lugar certo. Esta pergunta no Stack Overflow acumulou milhares de visualizações, e não é surpresa. Programação funcional em Kotlin não é apenas um recurso da moda, mas uma ferramenta poderosa que torna o código mais limpo, mais curto e mais expressivo.
\n\nNeste artigo, não vamos apenas dar uma resposta seca. Vamos abordar tudo, desde expressões lambda simples até técnicas avançadas. Você aprenderá como usar os tipos Function, o operador de referência a função ::, e até mesmo como evitar erros típicos de iniciantes. Vamos lá!
Por que isso é importante? Três razões para usar funções como parâmetros
\n\n- \n
- Flexibilidade: Você pode escrever uma função que fará coisas diferentes dependendo de qual função você passar para ela. \n
- Legibilidade: O código se torna declarativo — você descreve o que fazer, não como fazer. \n
- Reutilização: Elimina a duplicação de código, extraindo padrões comuns para funções de ordem superior. \n
Fundamentos: tipos de funções (Function Types)
\n\nEm Kotlin, funções são objetos de primeira classe. Isso significa que elas têm seu próprio tipo. O tipo de uma função é descrito assim: (Parâmetros) -> TipoRetorno. Por exemplo:
// Função que recebe um Int e retorna uma String\nval intToString: (Int) -> String = { number -> "Número: $number" }\n\n// Função que não recebe nada e não retorna nada\nval doNothing: () -> Unit = { println("Olá!") }\n\n// Função com dois parâmetros\nval sum: (Int, Int) -> Int = { a, b -> a + b }\n\n\nObserve o Unit — é o análogo ao void em Java/JavaScript. Se uma função não retorna nada, seu tipo é () -> Unit.
Como passar uma função como parâmetro: primeiro exemplo
\n\nSuponha que estamos escrevendo uma função que executa alguma operação em um número duas vezes. Em vez de fixar a operação, vamos passá-la como parâmetro:
\n\nfun applyTwice(x: Int, operation: (Int) -> Int): Int {\n val firstResult = operation(x)\n return operation(firstResult)\n}\n\n// Uso:\nval result = applyTwice(5) { it * 2 } // Lambda\nprintln(result) // Exibirá: 20 (5*2 = 10, 10*2 = 20)\n\n// Ou com uma função nomeada:\nfun double(x: Int) = x * 2\nval result2 = applyTwice(5, ::double)\nprintln(result2) // Também 20\n\n\nViu como é elegante? No primeiro caso, usamos uma expressão lambda (função anônima), e no segundo, uma referência a uma função existente através do operador ::. Ambas as formas são válidas, e vamos detalhá-las a seguir.
Formas de passar uma função (análise detalhada)
\n\n1. Expressões lambda (a forma mais popular)
\n\nLambda é uma função anônima que pode ser passada diretamente. Em Kotlin, lambdas têm uma sintaxe concisa:
\n\nval list = listOf(1, 2, 3, 4, 5)\n\n// Passando uma lambda para a função filter\nval evenNumbers = list.filter { it % 2 == 0 }\nprintln(evenNumbers) // [2, 4]\n\n// Se houver vários parâmetros:\nval numbersWithIndex = list.mapIndexed { index, value -> "$index: $value" }\nprintln(numbersWithIndex) // ["0: 1", "1: 2", ...]\n\n\nImportante: Se a lambda for o último parâmetro da função, ela pode ser colocada fora dos parênteses. Isso faz o código parecer com construções nativas da linguagem. É assim que funcionam filter, map, forEach e outros.
Exemplo com parâmetro explícito (quando há mais de um parâmetro):
\n\nfun performAction(a: Int, b: Int, action: (Int, Int) -> String) {\n println(action(a, b))\n}\n\n// Chamada com lambda\nperformAction(3, 4) { x, y -> "Soma: ${x + y}" }\n<