[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17269675#comment-17269675 ] Christopher Smith commented on TINKERPOP-2502: -- Putting on my API-client hat, "that's your job!" My thinking is going like this: The purpose of an interface is to support multiple implementations. Imagine we have a {{TraversalStartSteps}} interface defining our quad. - {{GraphTraversal implements TraversalStartSteps}} by simply doing the exact thing it already does, appending the new {{AddVertexStep}} to an ongoing traversal. - {{__.start()}} returns a {{GraphTraversal}}, so it's covered. - {{GraphTraversalSource implements TraversalStartSteps}} by doing the same thing it already does, which is to clone stuff _and add the "start steps" necessary to get it going_. As far as I can tell, by introducing {{TraversalStartSteps}}, client code can now initiate calling whichever of them regardless of whether they're initiating a blank traversal, appending to an existing one, or starting an anonymous subtraversal, and I don't think any further modification to any of the existing API is required, only creating this minimal superinterface. > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17269673#comment-17269673 ] Stephen Mallette commented on TINKERPOP-2502: - Sorry - I'm still not connecting something i guess - what will you do with a traversal that is not rigged up properly to actually execute? > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17269667#comment-17269667 ] Christopher Smith commented on TINKERPOP-2502: -- Internally, I don't especially care whether {{addV}} adds a "start step" or a "non-start step"; what I'm looking for is a consistent API so that I can write a single method that contains {{foo.addV().label('Stuff')...}} and initiate it consistently in either an anonymous or root context. With an anonymous traversal, I can say {{addStuff(__.start())}}, passing a {{GraphTraversal}} object, so we're good there. However, there's no way for me to get a plain/no-opped/whatever {{GraphTraversal}} out of {{GraphTraversalSource}}. The visible behavior is the same, and the method signatures are the same, but I can't abstract them together. > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17269658#comment-17269658 ] Stephen Mallette commented on TINKERPOP-2502: - thanks for the additional explanation. i dont think your suggestion to add {{GraphTraversalSource.start()}} will work because a blank traversal won't be rigged up properly to start. Note that there is a difference between {{GraphTraversal.addV()}} sorts of steps and {{GraphTraversalSource.addV()}} sorts of steps. Spawn steps in {{GraphTraversalSource}} will add a different sort of {{addV()}}-step that is designed to trigger the start of the traversal. Without that trigger nothing happens. your suggested {{GraphTraversalSource.start()}} would basically just be this: {code} return new DefaultGraphTraversal(this.clone()); {code} so rigged up in the console: {code} gremlin> g = TinkerGraph.open().traversal() ==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard] gremlin> new DefaultGraphTraversal(g.clone()).addV('person').iterate() gremlin> g ==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard] {code} I don't think a common interface helps you so well either as {{__}} are static. I could still be misunderstanding something though > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17267639#comment-17267639 ] Christopher Smith commented on TINKERPOP-2502: -- (You've probably encountered this before, but heads-up that Jira mangles anything including the name of the anonymous-traversal class.) > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17267638#comment-17267638 ] Christopher Smith commented on TINKERPOP-2502: -- I'm writing what's essentially a mini-OGM for Groovy, to be eventually implemented as a set of compile-time AST transformations to generate the repetitive part of mapping traversals. This is an extension method (in Java) that allows writing {{gts.addV(newPerson, PERSON_WRITER)}} (the logic might look familiar): {code:java} @SuppressWarnings("unchecked") // both traversal paths end in a Vertex public static GraphTraversal addV(GraphTraversalSource self, V entity, VertexWriter writer) { // https://stackoverflow.com/a/46053115/1189885 return self .V(entity.getLabelAndId().getId()).fold() .coalesce( whenExists(true, unfold()), whenExists(false, writer.createVertex(start(), entity)) ) .filter(select("existed").is(false)) .select("element"); } private static GraphTraversal> whenExists(boolean exists, GraphTraversal gt) { return gt.project("element", "existed").by(identity()).by(constant(exists)); } {code} However, this method can _only_ be called as {{gts.addV}}; it _cannot_ be called as {{__.addV}}, because there is no common supertype. Furthermore, while in the anonymous case (say, creating multiple vertices with edges between them) I could call {{__.start()}} to get a traversal to feed to the pipeline above, as I do to pass to {{createVertex}}, if I already have a {{GraphTraversalSource}} there's no way to turn it into a {{GraphTraversal}} except through {{V}}, {{E}}, {{addV}}, {{addE}}, or {{inject}} (potentially problematic with some implementations). Instead, if I had a method such as {{GraphTraversalSource#start()}} with the obvious semantics, I could modify the above method to accept a {{GraphTraversal}}, consume it for both anonymous and regular traversals, and provide sugar to adapt those cases onto it. > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)
[jira] [Commented] (TINKERPOP-2502) Consistent start API for anonymous and regular traversals
[ https://issues.apache.org/jira/browse/TINKERPOP-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17260515#comment-17260515 ] Stephen Mallette commented on TINKERPOP-2502: - I think I understand the problem you're describing, but I'm not quite picturing the weight of the frustration. Could you share some code that demonstrates how you librarify things? > Consistent start API for anonymous and regular traversals > - > > Key: TINKERPOP-2502 > URL: https://issues.apache.org/jira/browse/TINKERPOP-2502 > Project: TinkerPop > Issue Type: Improvement > Components: process >Affects Versions: 3.4.9 >Reporter: Christopher Smith >Priority: Minor > > I am writing a graph-based application and am taking advantage of the > method-based nature of Gremlin to librarify some of my common usage patterns. > However, I'm encountering a frustrating problem where I frequently need to be > able to attach the same traversal steps to either a real > {{GraphTraversalSource}} or an anonymous traversal (usually for some nested > reason like a coalesced conditional insert). > The methods on {{__}} are mostly static, but I can call {{__.start()}} to > obtain a live {{GraphTraversal}} object and then proceed from there (invoking > {{GraphTraversal#addV}}, for example). {{GraphTraversalSource}}, however, > requires me to invoke the method {{GraphTraversalSource#addV}} to get > started, and there's no common base type. I think I could theoretically use > something like {{inject()}}, but that seems particularly odd. > It would be helpful to either have both {{GraphTraversal}} and > {{GraphTraversalSource}} implement a common interface holding the "start > opcodes" or to have a {{GraphTraversalSource#start()}} method that could be > used to obtain a "blank" traversal. -- This message was sent by Atlassian Jira (v8.3.4#803005)