-
Notifications
You must be signed in to change notification settings - Fork 0
Modifying map to allow only key transform #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this 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
valueTransformandkeyTransformparameters optional in theMapoperator andmap()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.
There was a problem hiding this 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.
| * Where transforming function is not provided, original values will be | ||
| * preserved. |
Copilot
AI
Dec 19, 2025
There was a problem hiding this comment.
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.
| * 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. |
There was a problem hiding this 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.
| .. 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. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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.
| .. 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. |
| :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. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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.
| ===== | ||
|
|
||
| Map operator iterates over given stream source and applies transformation | ||
| functions one keys/values before yielding. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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".
| functions one keys/values before yielding. | |
| functions on keys/values before yielding. |
| ->map(function(array $row): Entity { | ||
| return Entity::fromArray($row); | ||
| }, function(int $key, array $row): string { | ||
| return $row['id']; | ||
| }); |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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 { ... }.
| ->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']; | |
| }, | |
| ); |
| .. 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. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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.
| :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. |
| .. php:class:: Filter | ||
| .. php:method:: __construct(iterable<TKey, TValue> $source, callable(TValue, TKey=): bool $filter = null) |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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.
| .. 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) |
| $this->finalized = true; | ||
|
|
||
| try { | ||
| yield from $this; |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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;
| * | ||
| * 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. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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".
| $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(...); |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
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.
Allow for map operator to support only key transform.
Can be leveraged for future operators, like
leftJoin, or similar.