Issues (85)

src/Operation/AsyncMapN.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace loophp\collection\Operation;
6
7
use Amp\Sync\LocalSemaphore;
8
use Closure;
9
use Exception;
10
use Generator;
11
12
use function Amp\Iterator\fromIterable;
13
use function Amp\ParallelFunctions\parallel;
14
use function Amp\Promise\wait;
15
use function Amp\Sync\ConcurrentIterator\map;
0 ignored issues
show
This use statement conflicts with another class in this namespace, loophp\collection\Operation\map. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
16
use function function_exists;
17
18 1
if (!function_exists('Amp\ParallelFunctions\parallel')) {
19
    throw new Exception('You need amphp/parallel-functions to get this operation working.');
20
}
21
22
/**
23
 * @immutable
24
 *
25
 * @template TKey
26
 * @template T
27
 */
28
final class AsyncMapN extends AbstractOperation
29
{
30
    /**
31
     * @return Closure(callable(mixed, mixed): mixed ...): Closure(iterable<TKey, T>): Generator<mixed, mixed>
32
     */
33 2
    public function __invoke(): Closure
34
    {
35 2
        return
36
            /**
37
             * @param callable(mixed, mixed): mixed ...$callbacks
38
             */
39 2
            static fn (callable ...$callbacks): Closure =>
40
                /**
41
                 * @param iterable<TKey, T> $iterable
42
                 *
43
                 * @return Generator<mixed, mixed>
44
                 */
45 2
                static function (iterable $iterable) use ($callbacks): Generator {
46 2
                    $callbackFactory =
47
                        /**
48
                         * @return Closure(mixed, callable(mixed, mixed): mixed): mixed
49
                         */
50 2
                        static fn (mixed $key): Closure =>
51
                            /**
52
                             * @param callable(mixed, mixed): mixed $callback
53
                             */
54
                            static fn (mixed $carry, callable $callback): mixed => $callback($carry, $key);
55
56 2
                    $callback =
57
                        /**
58
                         * @param array{0: mixed, 1: mixed} $value
59
                         *
60
                         * @return array{0: mixed, 1: mixed}
61
                         */
62 2
                        static fn (array $value): array => [$value[0], array_reduce($callbacks, $callbackFactory($value[0]), $value[1])];
63
64 2
                    $iter = map(fromIterable((new Pack())()($iterable)), new LocalSemaphore(32), parallel($callback));
65
66 2
                    while (wait($iter->advance())) {
67
                        /** @var array{0: mixed, 1: mixed} $item */
68 2
                        $item = $iter->getCurrent();
69
70 2
                        yield $item[0] => $item[1];
71
                    }
72 2
                };
73
    }
74
}
75