DEV Community

Cover image for Scala - Funções de Ordem Superior, Anônimas e Currying
João Gabriel Zó
João Gabriel Zó

Posted on • Updated on

Scala - Funções de Ordem Superior, Anônimas e Currying

Em linguagens funcionais, funções são tratadas como valores de primeira classe, permitindo a existência das funções de ordem superior.

Funções de Ordem Superior

Funções de ordem superior são funções que aceitam outras funções como argumento ou as retornam como resultado. Isso faz com que programas sejam compostos de uma forma mais flexível.

Dado as funções

def sum(f: Int => Int, a: Int, b: Int): Int = 
  if (a > b) 0
  else f(a) + sum(f, a + 1, b)
def cube(x: Int): Int = x * x * x

É possível compôr uma função que soma os cubos de um número

def sumCubes(a: Int, b: Int): Int = 
  sum(cube, a, b)

A => B é o tipo de uma função que recebe um argumento do tipo A e retorna um resultado do tipo B. Sendo assim, Int => Int recebe um argumento do tipo Int e retorna um resultado do mesmo tipo.

Funções Anônimas

O problema de passar funções como parâmetro é que isso leva à criação de diversas funções pequenas. Para evitar que isso aconteça, podemos criar funções sem dar um nome a elas. Essas funções são chamadas de funções anônimas.

(x: Int) => x * x * x

Na função acima, (x: Int) é o parâmetro da função, e x * x * x é o seu corpo.
O tipo do parâmetro pode ser omitido caso o compilador consiga inferir pelo contexto.

Uma função anônima (x1: T1, ..., xn: Tn) => E pode muito bem ser expressada utilizando def:

def F(x1: T1, ..., xn: Tn) = E

Se pode dizer então que funções anônimas são açúcares sintáticos.

Usando uma função anônima para reescrever a função sumCubes, ficaria da seguinte forma:

def sumCubes(a: Int, b: Int): Int = 
  sum(x => x * x * x, a, b)

Currying

A definição de funções que retornam funções é tão útil na programação funcional que existe uma sintaxe especial em Scala:

def sum(f: Int => Int)(a: Int, b: Int): Int = 
  if (a > b) 0
  else f(a) + sum(f)(a + 1, b)

Essa sintaxe especial se chama Currying.

O que o Currying faz é pegar uma função que recebe múltiplos parâmetros e transformar em uma cadeia de funções, cada uma recebendo 1 parâmetro.

Essa técnica facilita a criação de funções anônimas, e deixa mais fácil de passar uma função como objeto de primeira classe.

Além disso, ela abre a possibilidade de aplicá-la parcialmente a função, tornando-a mais flexível, da seguinte forma:

val sumCubes = sum(x => x * x * x)(_, _)

sumCubes(2, 5)

Esse post é o primeiro de uma série sobre Scala, que pretendo escrever a partir de anotações sobre as aulas do curso Functional Programming in Scala.

Top comments (0)