You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tinkerpop.apache.org by "Christopher Smith (Jira)" <ji...@apache.org> on 2021/01/19 04:12:00 UTC
[jira] [Comment Edited] (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 edited comment on TINKERPOP-2502 at 1/19/21, 4:11 AM:
------------------------------------------------------------------------
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 <V extends HasLabelAndId> GraphTraversal<Vertex, Vertex> addV(GraphTraversalSource self, V entity, VertexWriter<V> 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 <A> GraphTraversal<A, Map<String, Object>> whenExists(boolean exists, GraphTraversal<A, ?> 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. If I understand the semantics correctly, it would be as simple as cloning the other entry-point methods and dropping the {{addStep}} call.
was (Author: chrylis):
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 <V extends HasLabelAndId> GraphTraversal<Vertex, Vertex> addV(GraphTraversalSource self, V entity, VertexWriter<V> 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 <A> GraphTraversal<A, Map<String, Object>> whenExists(boolean exists, GraphTraversal<A, ?> 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)