Como faço para executar imediatamente uma função anônima em PHP?

96

Em JavaScript, você pode definir funções anônimas que são executadas imediatamente:

(function () { /* do something */ })()

Você pode fazer algo assim em PHP?

Emanuil Rusev
fonte
2
Não tenho php 5.3 em mãos para experimentar, mas como call_user_func(function(){/* stuff */})faço?
Jasper

Respostas:

120

Para PHP7: veja a resposta de Yasuo Ohgaki :(function() {echo 'Hi';})();

Para versões anteriores: a única maneira de executá-los imediatamente que consigo pensar é

call_user_func(function() { echo 'executed'; });
Gordon
fonte
12
A menos (ou até que) o encadeamento de chamadas de função seja introduzido, essa também seria minha sugestão.
Salathe de
2
@Gordon: php 5.4 ainda nada?
dinâmico
@ yes123 não. ainda tem que usarcall_user_func
Gordon
2
@BennettMcElwee vamos colocar desta forma: mesmo que a execução seja um pouco mais lenta do que a alternativa definir-atribuir-chamada, a probabilidade de isso representar um gargalo significativo em seu aplicativo é muito baixa. em caso de dúvida, crie o perfil de seu aplicativo em condições do mundo real.
Gordon
Obrigado @Gordon, foi o que pensei. Tive a impressão de que salathe e yes123 não estavam satisfeitos com esse método e me perguntei por quê. Parece perfeitamente bem para mim.
Bennett McElwee
28

Em PHP 7é fazer o mesmo em javascript

$gen = (function() {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;

O resultado é:

1
2
3
Wallace Maxters
fonte
15

Bem, é claro que você pode usar call_user_func, mas ainda há outra alternativa bem simples:

<?php
// we simply need to write a simple function called run:
function run($f){
    $f();
}

// and then we can use it like this:
run(function(){
    echo "do something";
});

?>
Pacerier
fonte
1
Eu quero uma função de execução imediata, porque a função que estou definindo é uma que NÃO DEVE ser chamada mais de uma vez na execução normal. O problema em definir uma função nomeada, run (), como você fez, é que qualquer outra pessoa que ver o código pode pensar que pode chamar run () também em alguma outra parte do código. A função de execução imediata deixa claro que esse código não deve ser executado duas vezes.
Daniel Howard
3
Eles não podem chamar runsua função em alguma outra parte do código porque não há nenhum identificador para sua função existente após a linha que a executa imediatamente.
Pacerier de
3
@DanielHoward O objetivo run()é executar imediatamente a função não nomeada transmitida a ele. O mesmo que call_user_func(), apenas nenhum parâmetro é passado.
Cypher
1
@JordanLev, tem uma implementação mais simples (apenas uma linha:) $f();e pode ser mais rápido se o mecanismo que você usa não otimiza para o caso especial em que call_user_functem apenas um argumento de função. Isso ocorre porque call_user_funcsuporta a passagem de vários parâmetros e seu primeiro argumento suporta uma string como um argumento ou uma função. Dito isso, se call_user_funcfor muito legível, eu não usaria run, a menos que o código estivesse localizado em algum lugar na parte inferior da pirâmide .
Pacerier,
1
@JordanLev, "implementação mais simples" refere-se à comparação entre o código dentro das funções rune call_user_func. call_user_functem uma desvantagem inerente quando comparado a runporque runfaz apenas uma coisa, enquanto call_user_funcoferece suporte a recursos adicionais, além de fazer o que runfaz. Você pode tentar um teste de loop rápido ( por exemplo ) para ver qual é mais rápido em seu motor.
Pacerier,
11

Este é o mais simples para PHP 7.0 ou posterior.

php -r '(function() {echo 'Hi';})();'

Significa criar um encerramento e, em seguida, chamá-lo como função seguindo "()". Funciona como JS graças à ordem de avaliação de variável uniforme.

https://3v4l.org/06EL3

Yasuo Ohgaki
fonte
2
Boa resposta, mas por que você a formata como uma operação de linha de comando?
Kodos Johnson
6
(new ReflectionFunction(function() {
 // body function
}))->invoke();
Innermond
fonte
6
você pode fornecer mais detalhes? talvez adicionar uma explicação?
MoralCode
2

Observação: uma resposta aceita está bem, mas leva 1,41x mais tempo (41% mais lento) do que declarar uma função e chamá-la em duas linhas.

[Sei que não é realmente uma resposta nova, mas achei valioso adicioná-la em algum lugar para os visitantes.]

Detalhes:

<?php
# Tags: benchmark, call_user_func, anonymous function 
require_once("Benchmark.php");
bench(array(
        'test1_anonfunc_call' => function(){
                $f = function(){
                        $x = 123;
                };
                $f();
        },
        'test2_anonfunc_call_user_func' => function(){
                call_user_func(
                        function(){
                                $x = 123;
                        }
                );
        }
), 10000);
?>

Resultados:

$ php test8.php
test1_anonfunc_call took 0.0081379413604736s (1228812.0001172/s)
test2_anonfunc_call_user_func took 0.011472940444946s (871616.13432805/s)
Shovas
fonte
0

Tentei desta forma, mas é mais prolixo do que a resposta principal, usando qualquer operador (ou função) que permite definir a função primeiro:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();
Paul Jerome Bordallo
fonte
2
Então por que não simplesmente $hack = function(){...}; $hack()?
0

Esta não é uma resposta direta, mas uma solução alternativa. Usando PHP> = 7. Definindo uma classe anônima com um método nomeado e construindo a classe e chamando o método imediatamente.

$var = (new class() { // Anonymous class
    function cool() { // Named method
        return 'neato';
    }
})->cool(); // Instantiate the anonymous class and call the named method
echo $var; // Echos neato to console.
thecoolestname 36
fonte
-2

Não executado imediatamente, mas perto de;)

<?php

$var = (function(){ echo 'do something'; });
$var();

?>
James
fonte