Skip to content

Conversation

@TheCelavi
Copy link
Member

No description provided.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This WIP PR refactors the reducer architecture to decrease memory footprint by fundamentally changing how reducers work. Instead of reducers being iterable streams themselves, they now implement a simpler next() method pattern that processes values one at a time.

Key changes:

  • Reducers no longer extend AbstractStream or implement IteratorAggregate; they now have a next(mixed $value, mixed $key) method for stateful value accumulation
  • The aggregators property has been renamed to aggregated throughout the codebase to better reflect its purpose
  • A new Reduce operator wraps reducers to provide streaming capability while reducing

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
StreamTest.php Updates test assertions to use the renamed aggregated property
Reducer test files (Sum, Min, Max, Count, Callback, Average) Refactored to test reducers through the reduce() function rather than directly instantiating them
Operator test files (BufferWhile, BufferCount) Updates assertions to use aggregated property
Collector test files Updates to access aggregated property from collectors
AggregatorTest.php Refactored to test aggregators with the new Reduce operator wrapper
functions.php Refactored reduce() and aggregate() functions to work with new reducer architecture, updated PHPDoc annotations
Stream.php Marked class as final, updated method signatures to accept callables as reducers
Reducer implementations Completely refactored from stream-based to stateful next() method pattern
Operator/Reduce.php New operator that wraps reducers to provide streaming with reduction
Contract interfaces ReducerInterface simplified to expose $value and next() method; StreamInterface and CollectorInterface updated with aggregated property
Collector implementations Updated to use aggregated property name
Aggregator.php Updated to work with new Reduce operator
AbstractStream.php Added aggregated property that maps aggregator values
Documentation files Various improvements to grammar, examples, and terminology consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +127 to 129
$this->aggregated = \array_map(
static fn(AggregatorInterface $aggregator): mixed => $aggregator->value,
$this->collection instanceof StreamInterface ? $this->collection->aggregators : [],
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aggregated property in StreamInterface already provides the mapped values (see AbstractStream lines 43-50 where it maps aggregators to their values). This code is redundantly mapping the aggregators again. It should be simplified to: $this->aggregated = $this->collection instanceof StreamInterface ? $this->collection->aggregated : [];

Copilot uses AI. Check for mistakes.
composer require runopencode/dataset
Nothing more is required, no additional initialization and/or configration. Just
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word is misspelled. It should be "configuration" not "configration".

Copilot uses AI. Check for mistakes.
echo \sprint('Total in EUR: %d', $stream->aggregated['total_converted']);
echo "\n";
echo \sprint('Average in EUR: %d', $stream->aggregators['average_converted']);
echo \sprint('Average in EUR: %d', $stream->aggregated['average_converted']);
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name appears to be misspelled. It should be sprintf, not sprint.

Copilot uses AI. Check for mistakes.
new Count([])->value;
$this->assertSame(
1,
reduce($dataset, Count::class, filter: static fn(int $value, string $key): bool => $key !== 'b' && $value !== 1)
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using named parameters with the reduce function won't work as expected. The reduce() function uses variadic parameters (...$args) which are passed positionally to the reducer constructor via ReflectionClass::newInstanceArgs(). Named parameters in the function call will be converted to positional arguments, which may not map correctly. The filter parameter should be passed as a positional argument instead.

Copilot uses AI. Check for mistakes.
new Max([])->value;
$this->assertEquals(
2,
reduce($dataset, Max::class, extractor: static fn(int $value, int $key): int => $value * $key),
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using named parameters with the reduce function won't work as expected. The reduce() function uses variadic parameters (...$args) which are passed positionally to the reducer constructor via ReflectionClass::newInstanceArgs(). Named parameters will not be properly mapped. The Max reducer constructor expects initial as the first parameter and extractor as the second, so this would need to pass null for initial before the extractor.

Copilot uses AI. Check for mistakes.

$this->assertEqualsWithDelta(
10.0,
reduce($dataset, Average::class, initial: 20),
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using named parameters with the reduce function won't work as expected. The reduce() function uses variadic parameters (...$args) which are passed positionally to the reducer constructor via ReflectionClass::newInstanceArgs(). Named parameters will not be properly mapped. The initial parameter should be passed as the first positional argument.

Copilot uses AI. Check for mistakes.
new Average([])->value;
$this->assertEqualsWithDelta(
4.0,
reduce($dataset, Average::class, countNull: true),
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using named parameters with the reduce function won't work as expected. The reduce() function uses variadic parameters (...$args) which are passed positionally to the reducer constructor via ReflectionClass::newInstanceArgs(). Named parameters will not be properly mapped. The countNull parameter is the third parameter in Average's constructor, so this would need to pass null for initial and extractor before countNull.

Copilot uses AI. Check for mistakes.
@TheCelavi TheCelavi closed this Dec 17, 2025
@TheCelavi TheCelavi deleted the dev branch December 17, 2025 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants