[ https://issues.apache.org/jira/browse/TINKERPOP-2491?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18015066#comment-18015066 ]
ASF GitHub Bot commented on TINKERPOP-2491: ------------------------------------------- andreachild commented on code in PR #3184: URL: https://github.com/apache/tinkerpop/pull/3184#discussion_r2287070581 ########## docs/src/upgrade/release-3.8.x.asciidoc: ########## @@ -490,6 +490,52 @@ The `GremlinLangScriptEngine` has been modified to treat float literals without or 'd') as Double by default. Users who need `BigDecimal` precision can still use the 'm' suffix (e.g., 1.0m). `GremlinGroovyScriptEngine` will still default to `BigDecimal` for `float` literals. +==== Consistent Collection Output for range(), limit(), and tail() Local Steps + +The `range(local)`, `limit(local)`, and `tail(local)` steps now consistently return collections rather than automatically +unfolding single-element results when operating on iterable collections (List, Set, etc.). Previously, when these steps +operated on collections and the result contained only one element, the step would return the single element directly +instead of a collection containing that element. + +This change ensures predictable return types based on the input type, making the behavior more consistent and intuitive. +Note that this change only affects iterable collections - Map objects continue to behave as before. + +[source,text] +---- +// 3.7.x and earlier - inconsistent output types for collections +gremlin> g.inject([1, 2, 3]).limit(local, 1) +==>1 // single element returned directly + +gremlin> g.inject([1, 2, 3]).limit(local, 2) +==>[1,2] // collection returned + +// 3.8.0 - consistent collection output for collections +gremlin> g.inject([1, 2, 3]).limit(local, 1) +==>[1] // collection always returned + +gremlin> g.inject([1, 2, 3]).limit(local, 2) +==>[1,2] // collection returned + +// Map behavior unchanged in both versions +gremlin> g.inject([a: 1, b: 2, c: 3]).limit(local, 1) +==>[a:1] // Map entry returned (behavior unchanged) +---- + +If you need the old behavior of extracting single elements from collections, you can add `.unfold()` after the local step: Review Comment: Added warning text area to specifically call out migration of existing queries that use the affected steps otherwise a class cast exception could occur or unpredictable results. > Improve consistency of the output of range() oriented steps > ----------------------------------------------------------- > > Key: TINKERPOP-2491 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2491 > Project: TinkerPop > Issue Type: Improvement > Components: process > Affects Versions: 3.4.9 > Reporter: Stephen Mallette > Priority: Major > Labels: breaking > > As pointed out here: > https://groups.google.com/g/gremlin-users/c/OvxKvvM8rXs/m/slnv6cWpBQAJ > there is an automatic {{List}} unfold with {{limit(local, 1)}} as in: > {code} > g.inject([1, 2, 3], [4]).limit(local, 3).toList() // [[1, 2, 3], [4]] > g.inject([1, 2, 3], [4]).limit(local, 2).toList() // [[1, 2], [4]] > g.inject([1, 2, 3], [4]).limit(local, 1).toList() // [1, 4] ??? - Expected > [[1], [4]] > g.inject([1, 2, 3], [4]).limit(local, 0).toList() // [[], []] oh come on > {code} > In addition, `range()` and `tail()` are similarly affected: > {code} > gremlin> g.inject([1, 2, 3], [4]).tail(local, 1).toList() > ==>3 > ==>4 > gremlin> g.inject([1, 2, 3], [4]).range(local, 0, 1).toList() > ==>1 > ==>4 > {code} > Changing this is a fairly imposing breaking change in behavior. We could > mitigate that with a strategy to support the old functionality if folks want > to have that: > {code} > g.withStrategy(OldWayStrategy).inject([1, 2, 3], [4]).limit(local, 1) > {code} > would transform to: > {code} > g.inject([1, 2, 3], [4]).limit(local, 1).unfold() > {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)