fp4php/functional

Streams

whsv26 opened this issue · 1 comments

image

  • Make Stream::range general
function generateJsonLinesFile(string $path): void
{
    Stream::infinite()
        ->map(fn() => new Foo(rand(), 1 === rand(0, 1), 1 === rand(0, 1)))
        ->map(fn(Foo $foo) => json_encode([$foo->a, $foo->b, $foo->c]))
        ->prepended(json_encode(["a", "b", "c"]))
        ->take(10000)
        ->intersperse(PHP_EOL)
        ->toFile($path);
}

/**
 * @return list<Foo>
 */
function parseJsonLinesFile(string $path): array
{
    $chars = function () use ($path): Generator {
        $file = new SplFileObject($path);
        while(false !== ($char = $file->fgetc())) {
            yield $char;
        }
        $file = null;
    };

    return Stream::emits($chars())
        ->groupAdjacentBy(fn($c) => PHP_EOL === $c)
        ->map(function ($pair) {
            return $pair[1]
                ->reduce(fn(string $acc, $cur) => $acc . $cur)
                ->getOrElse('[]');
        })
        ->filterMap('parseFoo')
        ->toArray();
}

/**
 * @return Option<Foo>
 */
function parseFoo(string $json): Option
{
    return jsonDecode($json)
        ->toOption()
        ->filter(fn($candidate) => is_array($candidate))
        ->filter(fn($candidate) => array_key_exists(0, $candidate) && is_int($candidate[0]))
        ->filter(fn($candidate) => array_key_exists(1, $candidate) && is_bool($candidate[1]))
        ->filter(fn($candidate) => array_key_exists(2, $candidate) && is_bool($candidate[2]))
        ->map(fn($tuple) => new Foo($tuple[0], $tuple[1], $tuple[2]));
}

$path = 'out.jsonl';
generateJsonLinesFile($path);
parseJsonLinesFile($path);