Search code examples
phpmatchphp-8

Use closures in match arms


When I run the following code with condition_2 being the match result the content of $foo is a closure instance, but I want the result that should be returned by that closure. How do you do this? condition_1 is working as expected.

$foo = match ($conditions) {
    'condition_1' => 'some text',
    'condition_2' => function () {
        $result = '';
        // crazy programming
        return $result;
    }
}

Solution

  • Just wrap the closure in call_user_func:

    $conditions = 'condition_2';
    $foo = match ($conditions) {
        'condition_1' => 'some text',
        'condition_2' => call_user_func(function () {
            $result = 'crazy';
            // crazy programming
            return $result;
        })
    };
    var_dump($foo);
    

    This code will result in the output of string(5) "crazy".

    Alternatively, you could store your closure in a variable and just call it:

    $myCallback = function () {
        $result = 'crazy';
        // crazy programming
        return $result;
    };
    $conditions = 'condition_2';
    $foo = match ($conditions) {
        'condition_1' => 'some text',
        'condition_2' => $myCallback()
    };
    

    There is a third way of going about this, where you could immediately call the closure if you add additional sets of parentheses (a tip of the hat to IMSoP for pointing it out in the comments):

    'condition_2' => (function () {
        $result = 'crazy';
        // crazy programming
        return $result;
    })()
    

    The first set wraps the closure and allows it to be interpreted (...closure definition...) and the second one is an empty set denoting a call of the function: wrapper -->(...closure definition...)()<-- call. Maybe slightly less readable, but eliminates any middlemen (an intermediary variable or a call to another function).