[ 
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)

Reply via email to