[
https://issues.apache.org/jira/browse/TINKERPOP3-716?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14947437#comment-14947437
]
Marko A. Rodriguez commented on TINKERPOP3-716:
-----------------------------------------------
I was thinking about this the other day. Unfortunately, not to the depth you
were discussing with your examples. However, my slight realization might
illuminate the situation.
I don't want to think of Gremlin has having "procedures." What is a
"procedure"? Its a step. A procedure can return an object, a List<object>, or
void. So can: {{map(traversal)}}, {{flatMap(traversal)}},
{{sideEffect(traversal)}}. Now, I think your main issue is the issue of
isolation. That is, can we make a traverser not be tied to the parent traversal
-- blank path, blank sack, 1 bulk, etc. Yes. One of two ways:
{code}
g.V.map(out('mother').name) // current -- the traverser is cloned into the nest
g.V.map(respawn().out('mother').name) // new -- clone ONLY the traverser's
location.
{code}
However, what about this:
{code}
g.V.map(respawn(sack,bulk,sideEffects).out('mother').name) // only location and
path stay
{code}
This is obviously not clean, but showing how we can leverage {{map}},
{{flatMap}}, {{filter}}, {{sideEffect}} as our "procedures" that return zero or
more results (like a procedure, but more natural to Gremlin). Finally, this
idea of {{respawn()}} allows us to control which aspects of the traverser to
propagate through and which not to.
.... don't know if this touches on your needs....
> subroutine step
> ---------------
>
> Key: TINKERPOP3-716
> URL: https://issues.apache.org/jira/browse/TINKERPOP3-716
> Project: TinkerPop 3
> Issue Type: Improvement
> Components: process
> Affects Versions: 3.0.1-incubating
> Reporter: Matt Frantz
> Assignee: Marko A. Rodriguez
>
> In our application, we build complex traversals. We use a modular technique
> in which lower-level traversals are used to compose higher-level traversals.
> For example, we might have an API like this:
> {code}
> void computeFoo(GraphTraversal t);
> {code}
> The assumption is that the "root" traversal has some state in the form of its
> traverser and path (and possible sack and side effects, although we're not
> using those at the moment). Importantly, all of this state is not fully
> realized, as the goal is to build another traversal before executing it all
> at once. To use the "foo" traversal in the "bar" traversal, I might do this:
> {code}
> void computeBar(GraphTraversal t) {
> // Perform some part of the "bar" calculation, including setting up the
> parameters of "foo"
> t.out()...;
> // Attach the "foo" logic.
> computeFoo(t);
> // Continue with more "bar" logic.
> t.blah()...;
> }
> {code}
> In the implementation of these modular traversals, we end up exposing certain
> implementation details, especially in the form of labeled steps (path keys).
> It is often the case that we don't necessarily want to leak this state. We
> often want these traversals to operate as if they were single steps,
> discarding any evidence of graph wandering that might have occurred.
> What if there were a step which acted as a "stack" for the path? (It might
> also act as a stack for the sack; we figured we would need that if we ever
> decide to use sack.) Not only would this provide encapsulation, it would
> allow the path to be pruned and thus improve runtime efficiency.
> We want traversal subroutines. How about this signature?
> {code}
> GraphTraversal sub(Traversal subTraversal);
> {code}
> What this would do is guarantee that no path state (or sack state) would
> escape. The only effect would be on the traverser. I think it could be
> implemented using a {{MapStep}}, or possibly {{FlatMapStep}} in order to
> realize a subTraversal that branches.
> What state would subTraversal have access to? By default, it could only see
> the traverser. It has its own key namespace for the path, so it cannot see
> the outer path. It has its own sack. It should probably have its own side
> effect key namespace, too.
> If you want to opt-in state into the subTraversal, then perhaps you could
> list the keys to form a pseudo-path:
> {code}
> GraphTraversal sub(Traversal subTraversal, String...stepOrSideEffectLabels);
> {code}
> One of the interesting things that this might provide (eventually) is the
> ability to hang OLTP traversal off of OLAP traversals. I had discussed this
> need a while ago in the context of vertices that act as OLAP "computation
> loci". A "sub" could use a different engine, and thus embed a standard
> traversal within a computer traversal.
> This would change our modular programming paradigm. We could safely redesign
> each module to produce an anonymous traversal like so:
> {code}
> GraphTraversal computeFoo();
> GraphTraversal computeBar() {
> // Perform some part of the "bar" calculation, including setting up the
> parameters of "foo"
> GraphTraversal t = __.out()...;
> // Attach the "foo" logic.
> t.sub(computeFoo(t));
> // Continue with more "bar" logic.
> return t.in()...;
> }
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)