Skip to content

Conversation

@TheCelavi
Copy link
Member

Allow for map operator to support only key transform.

Can be leveraged for future operators, like leftJoin, or similar.

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 PR enhances the map operator to support optional transformations, allowing callers to provide only a key transform, only a value transform, or both. This flexibility enables the operator to preserve original values or keys when only one type of transformation is needed, which can be leveraged for future operators like leftJoin.

Key Changes:

  • Made both valueTransform and keyTransform parameters optional in the Map operator and map() function
  • Added validation to ensure at least one transform function is provided
  • Updated type annotations to reflect the conditional return types based on which transforms are provided

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/RunOpenCode/Component/Dataset/src/Operator/Map.php Updated constructor to make both transform parameters optional, added validation logic, and updated documentation to reflect the new behavior
src/RunOpenCode/Component/Dataset/src/functions.php Updated map() function signature to make valueTransform optional and corrected PHPDoc return type annotations
src/RunOpenCode/Component/Dataset/tests/Operator/MapTest.php Renamed existing test and added three new test cases covering key-only, value-only, and validation scenarios

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

Copilot AI review requested due to automatic review settings December 19, 2025 09:37
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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


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

Comment on lines 19 to 20
* Where transforming function is not provided, original values will be
* preserved.
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The documentation states "original values will be preserved" but should be more accurate by stating "original values and/or keys will be preserved" since either transformation can be omitted independently. The current wording could be misinterpreted to suggest that only values are preserved when transformations are omitted.

Suggested change
* Where transforming function is not provided, original values will be
* preserved.
* Where transforming function is not provided, original values and/or keys
* will be preserved.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings December 23, 2025 13:01
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

Copilot reviewed 57 out of 57 changed files in this pull request and generated 9 comments.


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

Comment on lines 17 to 20
.. php:method:: __construct(iterable<TKey, TValue> $source, \Throwable|callable(): iterable<TKey, TValue> $fallback)
:param $source: ``iterable<TKey, TValue>`` Stream source to iterate over.
:param $fallback: ``\Throwable|callable(): iterable<TKey, TValue>`` Fallback stream source, or exception to throw.
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The documentation signature is missing the nullable type and default value for $fallback. According to the actual IfEmpty operator implementation, the parameter should be \Throwable|callable(): iterable<TKey, TValue>|null $fallback = null since it accepts null and defaults to creating a StreamEmptyException.

Suggested change
.. php:method:: __construct(iterable<TKey, TValue> $source, \Throwable|callable(): iterable<TKey, TValue> $fallback)
:param $source: ``iterable<TKey, TValue>`` Stream source to iterate over.
:param $fallback: ``\Throwable|callable(): iterable<TKey, TValue>`` Fallback stream source, or exception to throw.
.. php:method:: __construct(iterable<TKey, TValue> $source, \Throwable|callable(): iterable<TKey, TValue>|null $fallback = null)
:param $source: ``iterable<TKey, TValue>`` Stream source to iterate over.
:param $fallback: ``\Throwable|callable(): iterable<TKey, TValue>|null`` Fallback stream source, exception to throw, or ``null`` to use the default empty-stream exception.

Copilot uses AI. Check for mistakes.
:param $source: ``iterable<TKey, TValue>`` Stream source to iterate over.
:param $valueTransform: ``?callable(TValue, TKey=): TModifiedValue`` Optional transformation function for transforming values.
:param $keyTransform: ``?callable(TKey, TValue=): TModifiedKey`` Optional transformation function for transforming keys.
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The documentation is missing the parameter name for $keyTransform in the :param directive. It should be :param $keyTransform: instead of just starting with the type.

Copilot uses AI. Check for mistakes.
=====

Map operator iterates over given stream source and applies transformation
functions one keys/values before yielding.
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

There's a typo in "functions one keys/values" which should be "functions on keys/values".

Suggested change
functions one keys/values before yielding.
functions on keys/values before yielding.

Copilot uses AI. Check for mistakes.
Comment on lines 46 to 50
->map(function(array $row): Entity {
return Entity::fromArray($row);
}, function(int $key, array $row): string {
return $row['id'];
});
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The example uses positional arguments but doesn't make the intent clear. The first callable transforms values (array -> Entity) and the second transforms keys (extracting 'id' from the row). To improve clarity and match the pattern used in the test files, this example should use named parameters: valueTransform: function(array $row): Entity { ... }, keyTransform: function(int $key, array $row): string { ... }.

Suggested change
->map(function(array $row): Entity {
return Entity::fromArray($row);
}, function(int $key, array $row): string {
return $row['id'];
});
->map(
valueTransform: function(array $row): Entity {
return Entity::fromArray($row);
},
keyTransform: function(int $key, array $row): string {
return $row['id'];
},
);

Copilot uses AI. Check for mistakes.
.. php:method:: __construct(iterable<TKey, TValue> $source, ?callable(TValue, TKey=): string $identity = null)
:param $source: ``iterable<TKey, TValue>`` Stream to iterate over.
:param $predicate: ``?callable(TValue, TKey=): string`` User defined callable to determine item identity. If null, strict comparison (===) of values is used.
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The parameter name in the documentation is incorrect. The method signature shows the parameter is named $identity, but the parameter description refers to it as $predicate.

Suggested change
:param $predicate: ``?callable(TValue, TKey=): string`` User defined callable to determine item identity. If null, strict comparison (===) of values is used.
:param $identity: ``?callable(TValue, TKey=): string`` User defined callable to determine item identity. If null, strict comparison (===) of values is used.

Copilot uses AI. Check for mistakes.
.. php:class:: Filter
.. php:method:: __construct(iterable<TKey, TValue> $source, callable(TValue, TKey=): bool $filter = null)
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The method signature shows a default value of null for the $filter parameter, but the actual Filter operator constructor does not have a default value for this parameter (it's required). The documentation should remove = null from the signature.

Suggested change
.. php:method:: __construct(iterable<TKey, TValue> $source, callable(TValue, TKey=): bool $filter = null)
.. php:method:: __construct(iterable<TKey, TValue> $source, callable(TValue, TKey=): bool $filter)

Copilot uses AI. Check for mistakes.
$this->finalized = true;

try {
yield from $this;
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

This creates infinite recursion. The iterate() method yields from $this, which calls getIterator(), which calls iterate() again. This should yield from the source stream instead: yield from $this->source;

Copilot uses AI. Check for mistakes.
*
* Map operator iterates over given collection and yields transformed items.
* Map operator iterates over given stream source and applies transformation
* functions one keys/values before yielding.
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

There's a typo in "functions one keys/values" which should be "functions on keys/values".

Copilot uses AI. Check for mistakes.
$this->action = $action instanceof \Exception ? static fn(): never => throw $action : $action(...);
parent::__construct($source);
$fallback = $fallback ?? new StreamEmptyException();
$this->fallback = $fallback instanceof \Throwable ? static fn(): \Throwable => throw $fallback : $fallback(...);
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The closure return type annotation is incorrect. When $fallback is a \Throwable, the closure should be declared as static fn(): never => throw $fallback (not static fn(): \Throwable), since throwing always results in never returning. The current type suggests the closure returns an exception object, which is not what happens.

Copilot uses AI. Check for mistakes.
@TheCelavi TheCelavi merged commit ec332aa into master Dec 23, 2025
1 check passed
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.

3 participants