I guess there is an inconsistency here that should be resolved. Specifically, that means deciding on a behavior and then instituting appropriate tests to enforce that behavior. I agree with Kuppitz that the preferable way for this to work is to have that traversal be assert "2" as that is the number of iterations through the traversal that occurred. I'm not sure what the implementation challenges are with that, but that seems most logical an approach to me. If that's the consensus here then I'd suggest creating a ticket in JIRA and referencing this thread.
On Thu, Jan 26, 2017 at 11:14 AM, pieter-gmail <pieter.mar...@gmail.com> wrote: > Ping! > > Any ideas on this. > > Thanks > Pieter > > On 23/01/2017 19:00, pieter-gmail wrote: > > Hi, > > > > Ran some more tests, seems all is not well. > > > > So the previous example always works (on TinkerPop and Neo4j) because > > bothE is not seen as two queries but rather one and all is well. > > > > Running the same test with a union instead has the same issue as Sqlg. > > > > @Test > > public void testLazy() { > > final TinkerGraph graph = TinkerGraph.open(); > > final Vertex a1 = graph.addVertex(T.label, "A"); > > final Vertex b1 = graph.addVertex(T.label, "B"); > > final Vertex c1 = graph.addVertex(T.label, "C"); > > a1.addEdge("ab", b1); > > a1.addEdge("ac", c1); > > > > AtomicInteger count = new AtomicInteger(0); > > graph.traversal().V(a1).union(outE(), inE()).forEachRemaining(edge > -> { > > a1.addEdge("ab", b1); #1 > > c1.addEdge("ac", a1); #2 > > count.getAndIncrement(); > > }); > > Assert.assertEquals(2, count.get()); > > } > > > > If only #1 is executed the test passes as the outE() is first traversed > > and the subsequent inE() is unchanged. > > However is #2 is executed by the time inE() executes its sees 2 new in > > edges and the count == 4. > > > > I tested on Neo4j and it has the same behavior. > > > > As far as I can tell all is actually behaving as expected with lazy > > iteration assumed. > > > > The unspecified semantics is with bothE(), both sides done immediately > > like Neo4j and TinkerPop, or out and in done lazily as with Sqlg. > > If lazily which side first as if affects the semantics. > > > > Another caveat is if barrier steps are injected and then the semantics > > is not the same as without the barrier step. > > > > Cheers > > Pieter > > > > On 23/01/2017 14:38, Stephen Mallette wrote: > >> I'd say TinkerGraph demonstrates the expected behavior - I guess we > don't > >> have a test that enforces that? > >> > >> On Sat, Jan 21, 2017 at 3:23 PM, pieter-gmail <pieter.mar...@gmail.com> > >> wrote: > >> > >>> Ok, thanks. > >>> > >>> Its tricky as it messes with the laziness and visibility of the > queries. > >>> Can really think of a solution though. > >>> > >>> Cheers > >>> Pieter > >>> > >>> On 21/01/2017 21:14, Daniel Kuppitz wrote: > >>>> Hi Pieter, > >>>> > >>>> forEachRemaining iterates over the result and hence I would expect the > >>>> result to be 2. Otherwise you would / should end up with an endless > loop. > >>>> However, the same behavior is seen when you replace forEachRemaining > >>> with a > >>>> sideEffect lambda step. Not sure what the expected behavior is / > should > >>> be, > >>>> but I think I prefer the way it's done now. > >>>> > >>>> Cheers, > >>>> Daniel > >>>> > >>>> > >>>> On Sat, Jan 21, 2017 at 7:30 PM, pieter-gmail < > pieter.mar...@gmail.com> > >>>> wrote: > >>>> > >>>>> Hi, > >>>>> > >>>>> I need to clarify the expected semantics of gremlin's lazy iteration > >>>>> semantics. > >>>>> The following gremlin is what highlighted it. > >>>>> > >>>>> ``` > >>>>> @Test > >>>>> public void testLazy() { > >>>>> final TinkerGraph graph = TinkerGraph.open(); > >>>>> final Vertex a1 = graph.addVertex(T.label, "A"); > >>>>> final Vertex b1 = graph.addVertex(T.label, "B"); > >>>>> final Vertex c1 = graph.addVertex(T.label, "C"); > >>>>> a1.addEdge("ab", b1); > >>>>> a1.addEdge("ac", c1); > >>>>> > >>>>> AtomicInteger count = new AtomicInteger(0); > >>>>> graph.traversal().V(a1).bothE().forEachRemaining(edge -> { > >>>>> a1.addEdge("ab", b1); > >>>>> //a1.addEdge("ac", c1); > >>>>> count.getAndIncrement(); > >>>>> }); > >>>>> Assert.assertEquals(2, count.get()); > >>>>> } > >>>>> > >>>>> ``` > >>>>> > >>>>> On TinkerGraph the count is always 2. > >>>>> > >>>>> On Sqlg's Postgresql dialect the `bothE` first traverses the 'ac' > edges > >>>>> adds in a 'ab' edge and then traverses the 'ab' edges and ends up > with a > >>>>> count of 3. > >>>>> > >>>>> On Sqlg's HSQLDB and H2 dialects the `bothE` first traverses the 'ab' > >>>>> edges adds in a 'ab' edge then traverses the 'ac' edges and ends up > with > >>>>> a count of 2. > >>>>> > >>>>> So for Sqlg the added edge will be seen by subsequent traversals due > to > >>>>> the lazy nature but the order affects the result. > >>>>> > >>>>> TinkerGraph seems to get both 'ab' and 'ac' edges upfront and does > not > >>>>> subsequently see the added edge. A bit like it has a hidden barrier > step > >>>>> before the `forEachRemaining`. > >>>>> > >>>>> What is the expected semantics in this situation? > >>>>> Is a traversal that traverses an element that has been modified > earlier > >>>>> in the same traversal suppose to see the change? > >>>>> > >>>>> Thanks > >>>>> Pieter > >>>>> > >>>>> > >