Как сразу выполнить анонимную функцию в PHP?

96

В JavaScript вы можете определять анонимные функции, которые выполняются немедленно:

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

Можете ли вы сделать что-то подобное в PHP?

Эмануил Русев
источник
2
У меня нет под рукой php 5.3, чтобы попробовать, но как это call_user_func(function(){/* stuff */})сделать?
Джаспер

Ответы:

121

Для PHP7: см . Ответ Ясуо Огаки :(function() {echo 'Hi';})();

Для предыдущих версий: единственный способ выполнить их немедленно, о чем я могу думать, - это

call_user_func(function() { echo 'executed'; });
Гордон
источник
12
Если (или до тех пор, пока) не будет введена цепочка вызовов функций , это было бы моим предложением.
Салате
2
@Gordon: php 5.4 все еще ничего?
динамический
@ yes123 нет. еще придется использоватьcall_user_func
Гордон
2
@BennettMcElwee, скажем так: даже если это работает несколько медленнее, чем альтернатива определения-назначения-вызова, вероятность того, что это создаст серьезное узкое место в вашем приложении, очень мала. если есть сомнения, профилируйте свое приложение в реальных условиях.
Гордон
Спасибо, @Gordon, я так и думал. У меня сложилось впечатление, что салате и yes123 не понравился этот метод, и я задумался, почему. Мне кажется, это нормально.
Bennett McElwee
28

В PHP 7это сделать то же самое в JavaScript

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

    return 3;
})();

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

echo $gen->getReturn(), PHP_EOL;

Результат:

1
2
3
Уоллес Макстерс
источник
15

Конечно, вы можете использовать call_user_func, но есть еще одна довольно простая альтернатива:

<?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
источник
1
Мне нужна немедленно выполняющаяся функция, потому что определяемая мной функция НЕ ДОЛЖНА вызываться более одного раза при нормальном выполнении. Проблема с определением именованной функции run (), как и у вас, заключается в том, что любой, кто видит код, может подумать, что они могут вызвать run () также в какой-либо другой части кода. Функция, выполняющаяся немедленно, дает понять, что этот код не следует запускать дважды.
Дэниел Ховард,
3
Они не могут вызывать runвашу функцию в какой-либо другой части кода, потому что не существует дескриптора вашей функции после строки, которая немедленно ее выполняет.
Pacerier
3
@DanielHoward Смысл в run()том, чтобы немедленно выполнить переданную ему безымянную функцию. То же, что call_user_func(), только параметры не передаются.
Cypher
1
@JordanLev, он имеет более простую реализацию (всего одна строка :) $f();и может быть быстрее, если используемый вами движок не оптимизируется для особого случая, когда call_user_funcимеет только один аргумент функции. Это потому, что call_user_funcподдерживает передачу нескольких параметров, а его первый аргумент поддерживает либо строку в качестве аргумента, либо функцию. Тем не менее, если call_user_funcон хорошо читается, я бы не стал его использовать, runесли код не находится где-то в нижней части пирамиды .
Pacerier 02
1
@JordanLev, «более простая реализация» относится к сравнению кода внутри функций runи call_user_func. call_user_funcимеет присущий недостаток по сравнению с runпотому что runделает только одно, тогда как call_user_funcподдерживает дополнительные функции в дополнение к тому, что runделает. Вы можете попробовать быстрый цикл ( например ), чтобы увидеть, что быстрее на вашем движке.
Pacerier
11

Это самый простой вариант для PHP 7.0 или новее.

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

Это означает создать замыкание, а затем вызвать его как функцию, указав "()". Работает так же, как JS, благодаря единому порядку оценки переменных.

https://3v4l.org/06EL3

Ясуо Огаки
источник
2
Хороший ответ, но почему вы форматируете его как операцию из командной строки?
Кодос Джонсон
6
(new ReflectionFunction(function() {
 // body function
}))->invoke();
внутренний двор
источник
6
можете ли вы предоставить более подробную информацию? может добавить пояснение?
MoralCode 05
2

Обратите внимание: принятый ответ - это нормально, но он занимает в 1,41 раза больше времени (на 41% медленнее), чем объявление функции и ее вызов в две строки.

[Я знаю, что это не совсем новый ответ, но я чувствовал, что было бы полезно добавить его где-нибудь для посетителей.]

Подробности:

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

Полученные результаты:

$ php test8.php
test1_anonfunc_call took 0.0081379413604736s (1228812.0001172/s)
test2_anonfunc_call_user_func took 0.011472940444946s (871616.13432805/s)
Шовас
источник
0

Я попробовал это таким способом, но он более подробный, чем верхний ответ, с использованием любого оператора (или функции), который позволяет вам сначала определить функцию:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();
Пол Джером Бордалло
источник
2
Тогда почему не просто $hack = function(){...}; $hack()?
0

Это не прямой ответ, а обходной путь. Использование PHP> = 7. Определение анонимного класса с именованным методом и создание класса и немедленный вызов метода.

$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
источник
-2

Выполняется не сразу, но близко к;)

<?php

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

?>
Джеймс
источник