Home > Software design >  how to use array_reduce in immutable style?
how to use array_reduce in immutable style?

Time:11-20

I have been going through online study on a resource I quite liked till this very moment. The problem is they want my perfectly working array_reduce function is written "in immutable style". Which means that nothing should mutate inside, even accumulator. Which seems to me like making no sense. So, here is a piece of code I use in that study project they do not want to accept, function for flattening an array:

function flatten(array $tree)
{
    $result = array_reduce($tree, function ($acc, $item) {
        $newValue = is_array($item) ? flatten($item) : $item;
        if (!is_array($newValue)) {
            $acc[] = $newValue;
        } else {
            $acc = array_merge($acc, $newValue);
        }
        return $acc;
    }, []);
    return $result;
}

It works perfectly but this resourse (not free, BTW) does not accept it with notices "Should not use of mutating operators" to the lines where I change $acc.

So I ask them WTF and they answer me: do not change input argument and make a new acc instead and return this new acc from the callback. So I rewrite like this:

function flatten(array $tree)
{
    $result = array_reduce($tree, function ($acc, $item) {
        $accNew = $acc;
        $newValue = is_array($item) ? flatten($item) : $item;
        if (!is_array($newValue)) {
            $accNew[] = $newValue;
        } else {
            $accNew = array_merge($acc, $newValue);
        }
        return $accNew;
    }, []);
    return $result;
}

But this doesn't help, the same "Should not use of mutating operators" notices for the lines where now $accNew is being changed.

What the hell? I'm completely confused. Does this even make sense? Is this an appropriate demand? 'Cause I googled on it and it seems there are pretty much no people on Internet who were interested in using array_reduce "in immutable style"...

CodePudding user response:

I'm not 100% certain how this code gets used, but I think you might even be able to skip writing to the accumulator or a copy of it completely, and just return instead:

function flatten(array $tree): array
{
    return array_reduce(
        $tree,
        static function ($acc, $item) {
            $newValue = is_array($item) ? flatten($item) : $item;
            return array_merge($acc, is_array($newValue) ? $newValue : [$newValue]);
        },
        []
    );
}

Edit: My previous answer didn’t account for previous items in the accumulator, this does.

  • Related