Funções Anónimas

Neste artigo vamos falar de funções anónimas, da sua história,  a sua usabilidade e ainda mostrar dois exemplos de implementação. Um será em Python, enquanto o segundo será em JavaScript, ou seja, mais orientado para o contexto web. Mas antes de falarmos em funções anónimas vamos primeiro refletir sobre o que é uma função, que é algo, ligeiramente, complicado de explicar a um leigo em programação.

Já pensaram no que responderiam se lhes perguntassem o que é uma função? A mais simples resposta era fazer uma analogia com a Matemática: algo que aceita valores de entrada, transforma-os de alguma maneira e retorna algo no fim. Continuando com a analogia, em Matemática, costumamos dar nome às funções, assim como damos enquanto estamos a programar, mais corretamente designado por identificador. Agora imagine que tem uma função, mas que esse identificador não existia. Esta seria uma função que não tinha de estar ligada a qualquer identificador. Aqui temos o princípio básico das funções anónimas.

No presente artigo, vamos tratá-las por funções anónimas, mas são também conhecidas por funções lambda,  por terem sido criadas a partir do trabalho de Alonzo Church enquanto desenvolvia o cálculo lambda. Elas são típicas de linguagens funcionais, como o Haskell, Lisp, Ocaml, entre outras. Com o passar dos anos, outras linguagens arranjaram mecanismos de implementar estas funções como por exemplo C#, JavaScript, Python ou ainda Ruby.

Coloca-se uma nova questão: se estamos felizes com as funções comuns e parecem funcionar tão bem, porque devemos usar funções anónimas? E quando devemos usá-las? Dependendo da linguagem com que estamos habituados a programar, já deve ter surgido aquela situação em que o parâmetro de uma função é outra função. Aqui teríamos de declarar uma função no início ou no fim do bloco de código para ser usada uma única vez. Com as funções anónimas, e caso a linguagem suporte closure ganhamos uma maior simplicidade no código, escrevendo estas funções estrategicamente colocadas onde são usadas. São também muito utilizadas na técnica de currying, para transformar funções de múltiplos parâmetros numa cadeia de funções, onde apenas é passado um de cada vez.

Posto tudo isto, e como cada caso é um caso, vamos meter mãos à obra, primeiro com Python e depois com JavaScript, como já havia sido referido.

Em Python, ao contrário de JavaScript, o uso de funções anónimas é assegurado através da palavra reservada lambda, baseando-se no nome original dado a este tipo de funções, tal como descrito em cima. Este tipo de funções podem ser definidas em qualquer local do código e, como já referido anteriormente, sem um identificador respetivo. São muito utilizadas como complemento às funções de manuseamento de listas e outras estruturas semelhantes, tal como o map, filter e reduce. Para tornar mais claro esta informação segue em baixo a representação de duas funções, uma anónima e outra não. A versão utilizada do Python foi a 2.7.

  1. Cálculo do número N da sequência de Fibonacci, utilizando funções normais.
    def fib_normal(N):
      return N if N<2 else fibs(N-1)+fibs(N-2)
    print fib_normal(10)
  2. Cálculo do número N da sequência de Fibonacci, utilizando funções anónimas.
    fib_anonima = lambda N: N if N<2 else fib_anonima(N-1)+fib_anonima(N-2)
    print fib_anonima(10)

No exemplo em cima apresentado podemos ver que em ambos os casos é calculado a soma dos N primeiros elementos da sequência de  Fibonacci. No primeiro caso é apresentada a função fib_normal(N) que retorna essa soma, enquanto que no segundo caso o cálculo é feito recorrendo à declaração do lambda, que retorna essa mesma soma na variável fib_anonima.

Em JavaScript, não se torna muito diferente do exemplo anterior. Para declararmos uma função em JavasScript podemos fazer de duas formas:

    1. Declarando uma função com o seu nome, neste caso myFunction:
      function myFunction() {
        alert("Hello PaP!");
      }
    2. Ou ainda, usando o operador de função, tornando assim a função anónima:
      var myFunction = function() {
        alert("Hello PaP!");
      }

Repare-se que neste último caso a função não tem nome.

A grande diferença entre estes dois tipos, em termos de execução em JavaScript, é que as funções declaradas normalmente são movidas para o início do código e são criadas desde que o programa começa a execução. As que são escritas com o operador apenas são geradas quando chega o momento de as utilizar.

Este mecanismo permite uma diminuição do tempo de compilação, no entanto não permite a avaliação, por parte do compilador, de potenciais erros de execução que possam ocorrer durante a execução do programa.

Vamos ver outro exemplo em que as funções anónimas são habitualmente usadas em JavaScript:

var myFunction;
if(x!=0) {
  myFunction = function(){
    alert("!=0")
  }
}
else {
  myFunction = function(){
    alert("= 0")
  }
}

Neste exemplo, podemos ver que as instruções a desempenhar pela função representada pela variável myFunction serão diferentes consoante o valor de x.

Conclusão

As funções anónimas devem ser usadas conforme a experiência, a linguagem de desenvolvimento  e o objetivo do programador, tendo em conta que, normalmente, as soluções desenvolvidas com recurso a estas são mais elegantes e fáceis de ler. Mais ainda, podemos concluir que com o aparecimento do paradigma funcional nas linguagens de programação é possível utilizar todo potencial deste tipo de funções.

Esperamos ter agradado os leitores.