É possível ter uma função PHP recursiva e anônima? Esta é minha tentativa de fazê-lo funcionar, mas não passa o nome da função.
$factorial = function( $n ) use ( $factorial ) {
if( $n <= 1 ) return 1;
return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );
Também sei que essa é uma maneira ruim de implementar fatorial, é apenas um exemplo.
global $factorial
?print $factorial( 0);
Respostas:
Para que funcione, você precisa passar $ fatorial como referência
fonte
&
é por valor. Tudo com&
é por referência. "Objetos" não são valores no PHP5 e não podem ser atribuídos ou transmitidos. Você está lidando com uma variável cujo valor é uma referência a objeto. Como todas as variáveis, ele pode ser capturado por valor ou por referência, dependendo da existência de um&
.$factorial
será alterado antes da função ser chamada e poderá resultar em comportamento estranho.Sei que essa pode não ser uma abordagem simples, mas aprendi sobre uma técnica chamada "correção" em linguagens funcionais. A
fix
função de Haskell é conhecida mais geralmente como o combinador Y , que é um dos combinadores de ponto fixo mais conhecidos .Um ponto fixo é um valor inalterado por uma função: um ponto fixo de uma função f é qualquer x tal que x = f (x). Um combinador de ponto fixo y é uma função que retorna um ponto fixo para qualquer função f. Como y (f) é um ponto fixo de f, temos y (f) = f (y (f)).
Essencialmente, o combinador Y cria uma nova função que aceita todos os argumentos do original, além de um argumento adicional que é a função recursiva. Como isso funciona é mais óbvio usando a notação ao curry. Em vez de escrever argumentos entre parênteses (
f(x,y,...)
), escreva-os após a função:f x y ...
. O combinador Y é definido comoY f = f (Y f)
; ou, com um único argumento para a função recorrenteY f x = f (Y f) x
,.Desde o PHP não automaticamente caril funções, é um bocado de um hack para fazer
fix
o trabalho, mas eu acho que é interessante.Observe que isso é quase o mesmo que as soluções simples de fechamento postadas por outras pessoas, mas a função
fix
cria o fechamento para você. Os combinadores de ponto fixo são um pouco mais complexos do que usar um fechamento, mas são mais gerais e têm outros usos. Embora o método de fechamento seja mais adequado para PHP (que não é uma linguagem extremamente funcional), o problema original é mais um exercício do que para produção, portanto o combinador Y é uma abordagem viável.fonte
call_user_func_array()
é lento como o Natal.call_user_func_array
.array_unshift( $args, fix($func) );
? Args já está carregado com os parâmetros e a recursão real é feita pelo call_user_func_array (), então o que essa linha faz?Embora não seja para uso prático, a extensão no nível C mpyw-junks / phpext-callee fornece recursão anônima sem atribuir variáveis .
fonte
Nas versões mais recentes do PHP, você pode fazer isso:
Isso pode levar a um comportamento estranho.
fonte
Você pode usar o Y Combinator no PHP 7.1+ como abaixo:
Brinque com ele: https://3v4l.org/7AUn2
Códigos-fonte de: https://github.com/whitephp/the-little-phper/blob/master/src/chapter_9.php
fonte
Com uma classe anônima (PHP 7+), sem definir uma variável:
fonte