¿Cómo ejecuto inmediatamente una función anónima en PHP?

96

En JavaScript, puede definir funciones anónimas que se ejecutan inmediatamente:

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

¿Puedes hacer algo así en PHP?

Emanuil Rusev
fuente
2
No tengo php 5.3 en mis manos para probar, pero ¿cómo lo call_user_func(function(){/* stuff */})hago?
Jasper

Respuestas:

121

Para PHP7: vea la respuesta de Yasuo Ohgaki :(function() {echo 'Hi';})();

Para versiones anteriores: la única forma de ejecutarlas inmediatamente que se me ocurre es

call_user_func(function() { echo 'executed'; });
Gordon
fuente
12
A menos que (o hasta que) se introduzca el encadenamiento de llamadas a funciones , esta sería mi sugerencia también.
salathe
2
@Gordon: php 5.4 todavía nada?
dinámico
@ yes123 nop. todavía tengo que usarcall_user_func
Gordon
2
@BennettMcElwee digámoslo de esta manera: incluso si esto funciona algo más lento que la alternativa definir-asignar-llamar, la probabilidad de que esto represente un cuello de botella significativo en su aplicación es muy baja. en caso de duda, perfile tu aplicación en condiciones del mundo real.
Gordon
Gracias @Gordon, eso es lo que pensé. Tuve la impresión de que Salathe y yes123 no estaban contentos con este método y me preguntaba por qué. Me parece perfectamente bien.
Bennett McElwee
28

En PHP 7es hacer lo mismo en javascript.

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

    return 3;
})();

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

echo $gen->getReturn(), PHP_EOL;

La salida es:

1
2
3
Wallace Maxters
fuente
15

Bueno, por supuesto que puede usar call_user_func, pero todavía hay otra alternativa bastante simple:

<?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
fuente
1
Quiero una función que se ejecute inmediatamente, porque la función que estoy definiendo es una que NO DEBE ser llamada más de una vez en la ejecución normal. El problema con la definición de una función con nombre, run (), como lo ha hecho usted, es que cualquiera que vea el código puede pensar que también puede llamar a run () en alguna otra parte del código. La función de ejecución inmediata deja en claro que este código no debe ejecutarse dos veces.
Daniel Howard
3
No pueden llamar runa su función en alguna otra parte del código porque no existe un identificador para su función después de la línea que la ejecuta inmediatamente.
Pacerier
3
@DanielHoward El objetivo de run()es ejecutar inmediatamente la función sin nombre que se le ha pasado. Igual que call_user_func(), solo que no se pasan parámetros.
Cypher
1
@JordanLev, tiene una implementación más simple (solo una línea :) $f();y podría ser más rápido si el motor que usa no se optimiza para el caso especial donde call_user_funcsolo tiene un argumento de función. Esto se debe a que call_user_funcadmite el paso de múltiples parámetros y su primer argumento admite una cadena como argumento o una función. Dicho esto, si call_user_funces mucho más legible, no lo usaría a runmenos que el código esté ubicado en algún lugar en la parte inferior de la pirámide .
Pacerier
1
@JordanLev, "implementación más simple" se refiere a la comparación entre el código dentro de las funciones runy call_user_func. call_user_functiene una desventaja inherente en comparación con runporque runsolo hace una cosa, mientras que call_user_funcadmite funciones adicionales además de hacer lo que runhace. Puede probar una prueba de bucle rápido ( por ejemplo ) para ver cuál es más rápido en su motor.
Pacerier
11

Este es el más simple para PHP 7.0 o posterior.

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

Significa crear cierre, luego llamarlo como función siguiendo "()". Funciona igual que JS gracias al orden uniforme de evaluación de variables.

https://3v4l.org/06EL3

Yasuo Ohgaki
fuente
2
Buena respuesta, pero ¿por qué lo formatea como una operación de línea de comando?
Kodos Johnson
6
(new ReflectionFunction(function() {
 // body function
}))->invoke();
innermond
fuente
6
¿Puede proporcionar más detalles? tal vez agregar una explicación?
MoralCode
2

Tenga en cuenta que la respuesta aceptada está bien, pero tarda 1,41 veces más (41% más lento) que declarar una función y llamarla en dos líneas.

[Sé que no es una respuesta nueva, pero sentí que era valioso agregar esto en algún lugar para los visitantes].

Detalles:

<?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
fuente
0

Lo probé de esta manera, pero es más detallado que la respuesta principal al usar cualquier operador (o función) que le permita definir la función primero:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();
Paul Jerome Bordallo
fuente
2
Entonces, ¿por qué no simplemente $hack = function(){...}; $hack()?
0

Esta no es una respuesta directa, sino una solución. Usando PHP> = 7. Definir una clase anónima con un método con nombre y construir la clase y llamar al método de inmediato.

$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.
thecoolestname36
fuente
-2

No se ejecuta de inmediato, pero cerca de;)

<?php

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

?>
James
fuente