+2

PHP 5.3 parte 3: Lambda e Closures

criado por Douglas V. Pasqua em 05/01/2010 2:14pm
Nesta terceira parte de nossa série vamos abordar a utilização de Lambda e Closures que também foram recursos incluídos na versão 5.3. Funções Lambdas são conhecidas como funções anônimas. Closures são uma forma mais avançada de Lambdas permitindo trabalhar com funções anônimas de forma mais flexível e com menos limitações. Vamos entender agora o funcionamento desses dois novos rescursos.

Lambdas

Lambdas são conhecidas como funções anônimas. Estas funções podem ser definidas em qualquer lugar, podendo ser atribuídas à uma variável. A função existe somente no escopo de onde a variável foi definida. Caso a variável saia fora do escopo, a função também se torna indisponível.

É mais comum o uso de Lambdas em lugares que aceitam funções callback como parâmetro. Um exemplo é a função array_map. Segue a abaixo um exemplo usando função anônima com array_map:

<?php
$r = array_map(function($value) { // criando a função lambda como parâmetro para array_map
               return $value * 4;
              }, array(2, 4, 6, 8, 10));

print_r ($r);

A saída do script anterior será:

8
16
24
32
40

Perceba que usamos apenas 1 parâmetro na função anônima, $value:. O número de parâmetros varia de acordo com o número de arrays passados para a função array_map.

Poderíamos ter utilizado a função create_function, disponível desde a versão 4 do php, para criar funções anônimas. Porém tem algumas desvantagens. Uma delas é que ela é compilada em tempo de execução (runtime) ao invés de ser em tempo de compilação (compile time). Isto impacta no desempenho do script, além de ser uma syntax desagradável.

Comentários:

Mostrando 1 - 3 de 3 comentários
Respondendo a questão: Afinal, onde este método seria útil ?

O método __invoke pode ser usado para que uma classe se comporte como um closure. Imagino que a principal utilidade do closure seria em funções que aceitam callback como parâmetro. Funções como array_map, usort, etc.

Vamos supor que você queira criar diversas funções de comparação para utilizar em uma rotina de ordenação, como usort. Você pode criar diversas classes implementando o método __invoke e passar as instâncias dessas classes como parâmetro para a função usort.

Veja o exemplo abaixo para entender melhor:

<?php

class testeInvoke {
	public function __invoke($a, $b) {
		return(strcmp($a, $b));
	}
}

$o = new testeInvoke();
$array = array ("Ziraldo", "Luiz", "Joao", "Rodrigo", "Alberto");

usort($array, $o);
var_dump($array);

Criamos uma classe testeInvoke implementando o método mágico __invoke e passamos a sua instância para a função usort ordernar o array.

O resultado do script anterior:

# php invoke.php
array(5) {
  [0]=>
  string(7) "Alberto"
  [1]=>
  string(4) "Joao"
  [2]=>
  string(4) "Luiz"
  [3]=>
  string(7) "Rodrigo"
  [4]=>
  string(7) "Ziraldo"
}
06/01/2010 6:05pm (~15 anos atrás)

Aliás, o __invoke só é chamado quando a instância é invocada com os parênteses né? Acho que o primeiro exemplo do "$validacao = validacao()" nem funcionaria...
05/01/2010 9:40pm (~15 anos atrás)

Estive pensando: será que seria uma boa usar o __invoke para retornar a instância de uma classe singleton?

Algo assim:
$validacao = validacao::getInstance();

Ficaria apenas assim:
$validacao = validacao();

Não sei se isso tornaria o código menos intuitivo, já que "getInstance" é consagrado.

Mas se formos parar pra pensar: sempre que se usar o __invoke perderemos um pouco da legibilidade, afinal, estaremos omitindo o nome de um método. Afinal, onde este método seria útil?

Quem sabe para métodos que retornam objetos...
// Obtendo um usuario
$usuario = $alguma_coisa->usuario;

// Obtendo um usuario com codigo 1
$usuario = $alguma_coisa->usuario(3);

Enfim, as vezes o PHP tras umas coisas que nos faz pensar nas novas possibilidades...
05/01/2010 9:35pm (~15 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)