I think your argument makes sense but your example made me think of something else:
g.V().hasLabel('person').values('age').fold().where(all(gt(18))) the design of all() is to return true or false. if that's the case then using it in a where() will always be successful. returning true/false is really the job of a P so far and this would introduce something new. this direction could make sense if you wanted this: g.V().group().by('classroom').by(values('age').fold().all(gt(18)))) where you were trying to set the value of true/false to each "classroom" being over age 18. i'm not sure that's what we want all() to be doing exactly. i think it's intention is more like the one you supplied and i think it was meant more as a specialized filtering step, specialized in that it worked on List sorts of types only and more like the intention of the examples you used, as in: gremlin> g.V().hasLabel('person').values('age').fold().all(gt(18)) ==>[29,27,32,35] In this way, all()/any()/some() is a bit like how is() behaves in that it can apply a predicate to an item in the traversal stream. A good use case might be for dealing with results like: gremlin> g.V().both().both().group().by('name').by(outE().values('weight').fold()).unfold() ==>ripple=[] ==>peter=[0.2, 0.2, 0.2] ==>vadas=[] ==>josh=[1.0, 1.0, 1.0, 0.4, 0.4, 0.4, 1.0, 1.0, 1.0, 0.4, 0.4, 0.4, 1.0, 0.4] ==>lop=[] ==>marko=[0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 0.4, 0.5, 1.0, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0] where you dont even need to fold() the result. given the results above, i think folks might want to "find all key/value pairs where all weight values are gt(0.3)": g.V().both().both().group().by('name').by(outE().values('weight').fold()).unfold(). where(select(values).all(gt(0.3))) i think the analogous form today without all() would maybe be something like: gremlin> g.V().both().both().group().by('name').by(outE().values('weight').fold()).unfold(). ......1> filter(select(values). ......2> and(count(local).is(gt(0)), ......3> unfold().choose(__.is(gt(0.3)), constant(1), constant(0)). ......4> fold(). ......5> union(sum(local), count(local)).fold().as('x'). ......6> where('x',eq('x')).by(limit(local,1)).by(tail(local,1)))) ==>josh=[1.0, 1.0, 1.0, 0.4, 0.4, 0.4, 1.0, 1.0, 1.0, 0.4, 0.4, 0.4, 1.0, 0.4] ==>marko=[0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 0.4, 0.5, 1.0, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0] so, i think all() in this form does make good sense. it seems less of a type of P which would imply some sort of fold(), (i.e. stream consumption - has('weight',all(0.3))) into it which i think would complicate other forms that take P. making it more like an is() that is designed to work on a List seems best. i also don't think all() should do too much magic and force folks to fold() if they don't already have a List sort of type. That said, I'd be curious how you define all() to behave when it doesn't get that type or the List type is empty. I assume it would filter in those cases since that fits the current design direction made in other steps going back to mid-3.5.x releases. On Fri, Aug 4, 2023 at 9:29 PM Ken Hu <k...@bitquilltech.com.invalid> wrote: > Hi All, > > As I continue to take a further look into the list functions described in > Proposal 3, I noticed that they don't take in a Scope. Yet, it could have > been added because there are some functions that make sense as > ReducingBarriers. There are some instances, however, where the global scope > makes no sense so I would propose that we implement these as stated in > Proposal 3. I just want to point out that this would likely be the first > time local scope was used as a default for a Step (that isn't unfold) and > would like to give an opportunity for someone to voice their concerns about > this. > > Let's take a look at one of the examples from Proposal 3. > > List Example 1 (LE1) > Given a list of people, return the list of ages if everyone’s age > 18 > g.V().hasLabel('person').values('age').fold().where(all(gt(18))) > > Let's assume the proposal should have included this usage for all() that > takes a predicate as a parameter. If we remove the fold() from the above > example so that the example becomes > > g.V().hasLabel('person').values('age').where(all(gt(18))) > > If all() were to behave like a global scope step here then it would be > pretty meaningless as the incoming traverser is not a list type. In fact > the three proposed Steps that return boolean (all, any, none) shouldn't be > used unless the incoming traverser is an iterable type. In addition, the > set operations (intersect, union, disjunct and difference) also require the > incoming traverser to be a list/array type for them to have any sort of > meaning. I think it's reasonable for the default behavior of all the > proposed list functions to be the local scope versions. The concat() string > function has already set a precedent of not taking Scope as a parameter as > it currently only supports the global scope. In this case, for list > functions, we would only support local scope. If the user needs global > scope functionality then they would just need to add a fold() to their > query. > > Does anyone have objections to allowing this to become the default behavior > for these Steps? > > Thanks, > Ken >