Come posso eseguire immediatamente una funzione anonima in PHP?


96

In JavaScript, puoi definire funzioni anonime che vengono eseguite immediatamente:

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

Puoi fare qualcosa del genere in PHP?


2
Non ho php 5.3 tra le mani da provare, ma come si fa call_user_func(function(){/* stuff */})?
Jasper

Risposte:


121

Per PHP7: vedi la risposta di Yasuo Ohgaki :(function() {echo 'Hi';})();

Per le versioni precedenti: l'unico modo per eseguirle immediatamente mi viene in mente

call_user_func(function() { echo 'executed'; });

12
A meno che (o, fino a quando) non venga introdotto il concatenamento di chiamate di funzione , questo sarebbe anche il mio suggerimento.
Salathe il

2
@ Gordon: php 5.4 ancora niente?
dinamico

@ yes123 no. devono ancora usarecall_user_func
Gordon

2
@BennettMcElwee mettiamola in questo modo: anche se funziona un po 'più lentamente dell'alternativa definizione-assegnazione-chiamata, la probabilità che questo rappresenti un collo di bottiglia significativo nella tua applicazione è molto bassa. in caso di dubbio, profila la tua app in condizioni reali.
Gordon

Grazie @Gordon, è quello che ho pensato. Ho avuto l'impressione che salathe e yes123 non fossero contenti di questo metodo e mi sono chiesto perché. A me sembra perfettamente a posto.
Bennett McElwee

28

In PHP 7è fare lo stesso in javascript

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

    return 3;
})();

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

echo $gen->getReturn(), PHP_EOL;

L'output è:

1
2
3

15

Ovviamente puoi usare call_user_func, ma c'è ancora un'altra alternativa piuttosto semplice:

<?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";
});

?>

1
Voglio una funzione che venga eseguita immediatamente, perché la funzione che sto definendo è una che NON DOVREBBE essere chiamata più di una volta durante l'esecuzione normale. Il problema con la definizione di una funzione denominata, run (), come hai fatto tu, è che chiunque altro veda il codice potrebbe pensare di poter chiamare run () anche in qualche altra parte del codice. La funzione di esecuzione immediata rende chiaro che questo codice non deve essere eseguito due volte.
Daniel Howard

3
Non possono chiamare la runtua funzione in qualche altra parte del codice perché non esiste un handle per la tua funzione esistente dopo la riga che la esegue immediatamente.
Pacerier

3
@DanielHoward Lo scopo di run()è eseguire immediatamente la funzione senza nome che gli è stata passata. Uguale a call_user_func(), solo nessun parametro viene passato.
Cypher

1
@JordanLev, ha un'implementazione più semplice (solo una riga :) $f();e potrebbe essere più veloce se il motore che usi non ottimizza per il caso speciale in cui call_user_funcha un solo argomento di funzione. Questo perché call_user_funcsupporta il passaggio di più parametri e il suo primo argomento supporta una stringa come argomento o una funzione. Detto questo, se call_user_funcè molto leggibile, non lo userei arun meno che il codice non si trovi da qualche parte nella parte inferiore della piramide .
Pacerier

1
@JordanLev, "implementazione più semplice" si riferisce al confronto tra il codice all'interno delle funzioni rune call_user_func. call_user_funcha uno svantaggio intrinseco rispetto a runperché runfa solo una cosa, mentre call_user_funcsupporta funzionalità aggiuntive oltre a fare ciò che runfa. Puoi provare un rapido loop test ( ad esempio ) per vedere quale è più veloce sul tuo motore.
Pacerier

11

Questo è il più semplice per PHP 7.0 o versioni successive.

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

Significa creare chiusura, quindi chiamarla come funzione seguendo "()". Funziona proprio come JS grazie all'ordine di valutazione delle variabili uniforme.

https://3v4l.org/06EL3


2
Buona risposta, ma perché lo formatti come operazione da riga di comando?
Kodos Johnson

6
(new ReflectionFunction(function() {
 // body function
}))->invoke();

6
puoi fornire maggiori dettagli? magari aggiungere una spiegazione?
morale

2

Nota, la risposta accettata va bene, ma richiede 1,41 volte il tempo (41% più lento) rispetto alla dichiarazione di una funzione e alla sua chiamata su due righe.

[So che non è proprio una nuova risposta, ma ho ritenuto che fosse utile aggiungerla da qualche parte per i visitatori.]

Dettagli:

<?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);
?>

Risultati:

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

0

L'ho provato in questo modo, ma è più prolisso della risposta principale utilizzando qualsiasi operatore (o funzione) che ti consenta di definire prima la funzione:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();

2
Allora perché non semplicemente $hack = function(){...}; $hack()?

0

Questa non è una risposta diretta, ma una soluzione alternativa. Utilizzo di PHP> = 7. Definizione di una classe anonima con un metodo denominato, costruzione della classe e chiamata immediata del metodo.

$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.

-2

Non eseguito immediatamente, ma vicino a;)

<?php

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

?>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.