You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/08/31 18:36:17 UTC

incubator-tinkerpop git commit: I think I'm going down the wrong path here. I'm going to commit this, but will start another branch with a much simpler solution --- though I haven't throught it through completely. Lets see.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/sack_split_merge 26091c43e -> eae8d9f2c


I think I'm going down the wrong path here. I'm going to commit this, but will start another branch with a much simpler solution --- though I haven't throught it through completely. Lets see.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/eae8d9f2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/eae8d9f2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/eae8d9f2

Branch: refs/heads/sack_split_merge
Commit: eae8d9f2c99e044622999d902ed1d6eb6384f578
Parents: 26091c4
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Aug 31 10:36:15 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Aug 31 10:36:15 2015 -0600

----------------------------------------------------------------------
 .../traversal/VertexTraversalSideEffects.java   | 11 +++-
 .../process/traversal/TraversalSideEffects.java | 30 ++++++----
 .../dsl/graph/GraphTraversalSource.java         | 61 ++++++++++++++++----
 .../traversal/step/map/ConstantStep.java        |  2 +-
 .../finalization/SackSplitterStrategy.java      | 23 ++------
 .../traverser/B_LP_O_P_S_SE_SL_Traverser.java   |  2 +-
 .../traverser/B_LP_O_S_SE_SL_Traverser.java     |  2 +-
 .../traverser/B_O_S_SE_SL_Traverser.java        |  8 ++-
 .../util/DefaultTraversalSideEffects.java       | 17 ++++--
 .../util/EmptyTraversalSideEffects.java         |  8 ++-
 .../tinkergraph/structure/TinkerGraphTest.java  | 18 +++---
 11 files changed, 124 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/VertexTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/VertexTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/VertexTraversalSideEffects.java
index 1414e12..ede4c1d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/VertexTraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/VertexTraversalSideEffects.java
@@ -27,8 +27,8 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -59,7 +59,7 @@ public final class VertexTraversalSideEffects implements TraversalSideEffects {
     }
 
     @Override
-    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S,Long,Long,S>> splitOperator) {
+    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitFunction, final Optional<BinaryOperator<S>> mergeOperator) {
         throw EXCEPTION;
     }
 
@@ -69,7 +69,12 @@ public final class VertexTraversalSideEffects implements TraversalSideEffects {
     }
 
     @Override
-    public <S> Optional<TriFunction<S,Long,Long,S>> getSackSplitter() {
+    public <S> Optional<TriFunction<S, Long, Long, S>> getSackSplitter() {
+        throw EXCEPTION;
+    }
+
+    @Override
+    public <S> Optional<BinaryOperator<S>> getSackMerger() {
         throw EXCEPTION;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
index b390444..0306770 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
@@ -25,9 +25,8 @@ import java.io.Serializable;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
 
 /**
  * A {@link Traversal} can maintain global sideEffects.
@@ -108,14 +107,16 @@ public interface TraversalSideEffects extends Cloneable, Serializable {
     }
 
     /**
-     * Set the initial value of each {@link Traverser} "sack" along with the operator for splitting sacks.
-     * If no operator is provided, then a direct memory copy is assumed (this is typically good for primitive types and strings).
+     * Set the initial value of each {@link Traverser} "sack" along with the functions for splitting sacks and merging sacks.
+     * If no split is provided, then a direct memory copy is assumed (this is typically good for primitive types and strings).
+     * If no merge is provided, then traversers are never merged.
      *
      * @param initialValue  the initial value supplier of the traverser sack
-     * @param splitOperator the split operator for splitting traverser sacks
+     * @param splitFunction the split function for splitting traverser sacks
+     * @param mergeOperator the merge operator for merging traverser sacks
      * @param <S>           the sack type
      */
-    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S,Long,Long,S>> splitOperator);
+    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitFunction, final Optional<BinaryOperator<S>> mergeOperator);
 
     /**
      * If sacks are enabled, get the initial value of the {@link Traverser} sack.
@@ -126,13 +127,22 @@ public interface TraversalSideEffects extends Cloneable, Serializable {
     public <S> Optional<Supplier<S>> getSackInitialValue();
 
     /**
-     * If sacks are enabled and a split operator has been specified, then get it.
-     * The split operator is used to split a stack when a bifurcation in a {@link Traverser} happens.
+     * If sacks are enabled and a split function has been specified, then get it.
+     * The split function is used to split a stack when a furcation in a {@link Traverser} happens.
      *
      * @param <S> the sack type
-     * @return the operator for splitting a traverser sack
+     * @return the function for splitting a traverser sack
      */
-    public <S> Optional<TriFunction<S,Long,Long,S>> getSackSplitter();
+    public <S> Optional<TriFunction<S, Long, Long, S>> getSackSplitter();
+
+    /**
+     * If sacks are enabled and a merge operator has been specified, then get it.
+     * The merge operator is use to merge two sacks together into one sack.
+     *
+     * @param <S> the sack type
+     * @return the operator for merging two traverser sacks
+     */
+    public <S> Optional<BinaryOperator<S>> getSackMerger();
 
     /**
      * If the sideEffect contains an object associated with the key, return it.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index 3081546..743b8a8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -41,6 +41,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 
@@ -151,25 +152,45 @@ public class GraphTraversalSource implements TraversalSource {
 
     public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final TriFunction<A, Long, Long, A> splitFunction) {
         final GraphTraversal.Admin traversal = this.generateTraversal();
-        traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction));
+        traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction), Optional.empty());
         return new GraphTraversalSourceStub(traversal, false);
     }
 
     public <A> GraphTraversalSourceStub withSack(final A initialValue, final TriFunction<A, Long, Long, A> splitFunction) {
         final GraphTraversal.Admin traversal = this.generateTraversal();
-        traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction));
+        traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction), Optional.empty());
+        return new GraphTraversalSourceStub(traversal, false);
+    }
+
+    public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final UnaryOperator<A> splitOperator, final BinaryOperator<A> mergeOperator) {
+        return this.withSack(initialValue, UnaryTriFunction.toTriFunction(splitOperator), mergeOperator);
+    }
+
+    public <A> GraphTraversalSourceStub withSack(final A initialValue, final UnaryOperator<A> splitOperator, final BinaryOperator<A> mergeOperator) {
+        return this.withSack(initialValue, UnaryTriFunction.toTriFunction(splitOperator), mergeOperator);
+    }
+
+    public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final TriFunction<A, Long, Long, A> splitFunction, final BinaryOperator<A> mergeOperator) {
+        final GraphTraversal.Admin traversal = this.generateTraversal();
+        traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction), Optional.of(mergeOperator));
+        return new GraphTraversalSourceStub(traversal, false);
+    }
+
+    public <A> GraphTraversalSourceStub withSack(final A initialValue, final TriFunction<A, Long, Long, A> splitFunction, final BinaryOperator<A> mergeOperator) {
+        final GraphTraversal.Admin traversal = this.generateTraversal();
+        traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction), Optional.of(mergeOperator));
         return new GraphTraversalSourceStub(traversal, false);
     }
 
     public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue) {
         final GraphTraversal.Admin traversal = this.generateTraversal();
-        traversal.getSideEffects().setSack(initialValue, Optional.empty());
+        traversal.getSideEffects().setSack(initialValue, Optional.empty(), Optional.empty());
         return new GraphTraversalSourceStub(traversal, false);
     }
 
     public <A> GraphTraversalSourceStub withSack(final A initialValue) {
         final GraphTraversal.Admin traversal = this.generateTraversal();
-        traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.empty());
+        traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.empty(), Optional.empty());
         return new GraphTraversalSourceStub(traversal, false);
     }
 
@@ -305,33 +326,53 @@ public class GraphTraversalSource implements TraversalSource {
             return this;
         }
 
+        public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final UnaryOperator<A> splitOperator, final BinaryOperator<A> mergeOperator) {
+            this.traversal.getSideEffects().setSack(initialValue, Optional.of(UnaryTriFunction.toTriFunction(splitOperator)), Optional.of(mergeOperator));
+            return this;
+        }
+
+        public <A> GraphTraversalSourceStub withSack(final A initialValue, final UnaryOperator<A> splitOperator, final BinaryOperator<A> mergeOperator) {
+            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(UnaryTriFunction.toTriFunction(splitOperator)), Optional.of(mergeOperator));
+            return this;
+        }
+
+        public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final TriFunction<A, Long, Long, A> splitFunction, final BinaryOperator<A> mergeOperator) {
+            this.traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction), Optional.of(mergeOperator));
+            return this;
+        }
+
+        public <A> GraphTraversalSourceStub withSack(final A initialValue, final TriFunction<A, Long, Long, A> splitFunction, final BinaryOperator<A> mergeOperator) {
+            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction), Optional.of(mergeOperator));
+            return this;
+        }
+
         public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final UnaryOperator<A> splitOperator) {
-            this.traversal.getSideEffects().setSack(initialValue, Optional.of(UnaryTriFunction.toTriFunction(splitOperator)));
+            this.traversal.getSideEffects().setSack(initialValue, Optional.of(UnaryTriFunction.toTriFunction(splitOperator)), Optional.empty());
             return this;
         }
 
         public <A> GraphTraversalSourceStub withSack(final A initialValue, final UnaryOperator<A> splitOperator) {
-            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(UnaryTriFunction.toTriFunction(splitOperator)));
+            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(UnaryTriFunction.toTriFunction(splitOperator)), Optional.empty());
             return this;
         }
 
         public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue, final TriFunction<A, Long, Long, A> splitFunction) {
-            this.traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction));
+            this.traversal.getSideEffects().setSack(initialValue, Optional.of(splitFunction), Optional.empty());
             return this;
         }
 
         public <A> GraphTraversalSourceStub withSack(final A initialValue, final TriFunction<A, Long, Long, A> splitFunction) {
-            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction));
+            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.of(splitFunction), Optional.empty());
             return this;
         }
 
         public <A> GraphTraversalSourceStub withSack(final Supplier<A> initialValue) {
-            this.traversal.getSideEffects().setSack(initialValue, Optional.empty());
+            this.traversal.getSideEffects().setSack(initialValue, Optional.empty(), Optional.empty());
             return this;
         }
 
         public <A> GraphTraversalSourceStub withSack(final A initialValue) {
-            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.empty());
+            this.traversal.getSideEffects().setSack(new ConstantSupplier<>(initialValue), Optional.empty(), Optional.empty());
             return this;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 5d02e28..7219585 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -27,7 +27,7 @@ import java.util.Collections;
 import java.util.Objects;
 import java.util.Set;
 
-public class ConstantStep<S, E> extends MapStep<S, E> {
+public final class ConstantStep<S, E> extends MapStep<S, E> {
 
     private final E constant;
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SackSplitterStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SackSplitterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SackSplitterStrategy.java
index b6501a6..2aaafaf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SackSplitterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SackSplitterStrategy.java
@@ -23,15 +23,11 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SackSplitterStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.util.function.UnaryTriFunction;
 
 import java.util.Collections;
 import java.util.List;
@@ -50,23 +46,14 @@ public final class SackSplitterStrategy extends AbstractTraversalStrategy<Traver
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (traversal.getSideEffects().getSackSplitter().isPresent()) {
+        /*if (traversal.getSideEffects().getSackSplitter().isPresent() && !(traversal.getSideEffects().getSackSplitter().get() instanceof UnaryTriFunction)) {
             if (!(traversal.getParent() instanceof SackSplitterStep)) {
-                final List<Step> stepsToWrap = traversal.getSteps().stream().
-                        filter(step -> !(step instanceof MapStep ||
-                                step instanceof FilterStep ||
-                                step instanceof BranchStep ||
-                                step instanceof RepeatStep ||
-                                step instanceof RepeatStep.RepeatEndStep ||
-                                step instanceof SideEffectStep ||
-                                step instanceof SackSplitterStep ||
-                                step instanceof GraphStep)).
-                        collect(Collectors.toList());
+                final List<Step> stepsToWrap = traversal.getSteps().stream().filter(step -> step instanceof FlatMapStep).collect(Collectors.toList());
                 for (final Step step : stepsToWrap) {
                     TraversalHelper.replaceStep(step, new SackSplitterStep<>(traversal, __.start().identity().asAdmin().addStep(step)), traversal);
                 }
             }
-        }
+        }*/
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
index c282d30..a5c88dd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
@@ -92,7 +92,7 @@ public class B_LP_O_P_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
                 && ((B_LP_O_P_S_SE_SL_Traverser) object).get().equals(this.t)
                 && ((B_LP_O_P_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
                 && ((B_LP_O_P_S_SE_SL_Traverser) object).loops() == this.loops()
-                && (null == this.sack)
+                && (null == this.sack || this.getSideEffects().getSackMerger().isPresent())
                 && ((B_LP_O_P_S_SE_SL_Traverser) object).path().equals(this.path);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
index f9c2e08..b63178a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
@@ -97,7 +97,7 @@ public class B_LP_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
                 && ((B_LP_O_S_SE_SL_Traverser) object).get().equals(this.t)
                 && ((B_LP_O_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
                 && ((B_LP_O_S_SE_SL_Traverser) object).loops() == this.loops()
-                && (null == this.sack)
+                && (null == this.sack || this.getSideEffects().getSackMerger().isPresent())
                 && ((B_LP_O_S_SE_SL_Traverser) object).path().popEquals(Pop.last,this.path); // this should be Pop.all?
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
index 8d58080..9c9131d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_S_SE_SL_Traverser.java
@@ -102,6 +102,12 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
         return clone;
     }
 
+    @Override
+    public void merge(final Traverser.Admin<?> other) {
+        super.merge(other);
+        this.sack = null == this.sack ? null : this.sideEffects.getSackMerger().orElse((a, b) -> a).apply(this.sack, other.sack());
+    }
+
     /////////////////
 
     @Override
@@ -115,6 +121,6 @@ public class B_O_S_SE_SL_Traverser<T> extends B_O_Traverser<T> {
                 && ((B_O_S_SE_SL_Traverser) object).get().equals(this.t)
                 && ((B_O_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
                 && ((B_O_S_SE_SL_Traverser) object).loops() == this.loops()
-                && (null == this.sack);
+                && (null == this.sack || this.getSideEffects().getSackMerger().isPresent());
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
index ff193b4..605f477 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalSideEffects.java
@@ -31,7 +31,9 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -40,7 +42,8 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
 
     protected Map<String, Object> objectMap = new HashMap<>();
     protected Map<String, Supplier> supplierMap = new HashMap<>();
-    protected TriFunction sackSplitOperator = null;
+    protected TriFunction sackSplitFunction = null;
+    protected BinaryOperator sackMergeOperator = null;
     protected Supplier sackInitialValue = null;
 
     public DefaultTraversalSideEffects() {
@@ -75,9 +78,10 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
     }
 
     @Override
-    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitOperator) {
+    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitFunction, final Optional<BinaryOperator<S>> mergeOperator) {
         this.sackInitialValue = initialValue;
-        this.sackSplitOperator = splitOperator.orElse(null);
+        this.sackSplitFunction = splitFunction.orElse(null);
+        this.sackMergeOperator = mergeOperator.orElse(null);
     }
 
     @Override
@@ -87,7 +91,12 @@ public class DefaultTraversalSideEffects implements TraversalSideEffects {
 
     @Override
     public <S> Optional<TriFunction<S, Long, Long, S>> getSackSplitter() {
-        return Optional.ofNullable(this.sackSplitOperator);
+        return Optional.ofNullable(this.sackSplitFunction);
+    }
+
+    @Override
+    public <S> Optional<BinaryOperator<S>> getSackMerger() {
+        return Optional.ofNullable(this.sackMergeOperator);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalSideEffects.java
index 5d8c1e4..c0e1baa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/EmptyTraversalSideEffects.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.util.function.TriFunction;
 import java.util.Collections;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
 
 /**
@@ -69,7 +70,7 @@ public final class EmptyTraversalSideEffects implements TraversalSideEffects {
     }
 
     @Override
-    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitOperator) {
+    public <S> void setSack(final Supplier<S> initialValue, final Optional<TriFunction<S, Long, Long, S>> splitFunction, final Optional<BinaryOperator<S>> mergeOperator) {
 
     }
 
@@ -84,6 +85,11 @@ public final class EmptyTraversalSideEffects implements TraversalSideEffects {
     }
 
     @Override
+    public <S> Optional<BinaryOperator<S>> getSackMerger() {
+        return Optional.empty();
+    }
+
+    @Override
     public void setLocalVertex(final Vertex vertex) {
 
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/eae8d9f2/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
index af70f7d..1c942a8 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
@@ -20,12 +20,9 @@ package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -34,6 +31,7 @@ import org.apache.tinkerpop.gremlin.structure.io.IoCore;
 import org.apache.tinkerpop.gremlin.structure.io.IoTest;
 import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLIo;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
+import org.apache.tinkerpop.gremlin.util.function.UnaryTriFunction;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -41,7 +39,6 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.function.Supplier;
 
@@ -171,7 +168,12 @@ public class TinkerGraphTest {
         //System.out.println(g.V().properties().key().groupCount().next());
         TinkerGraph graph = TinkerFactory.createModern();
         GraphTraversalSource g = graph.traversal(GraphTraversalSource.standard());
-        final Traversal traversal = g.withSack(1.0,(a,b,c)-> ((double)b/(double)c) * a).V().repeat(out()).times(2).sack();
+        final Traversal traversal = g.withSack(1.0, UnaryTriFunction.identity(),(a,b) -> a+b).V(1).
+                outE("knows").<Double,Long>sack((a, b) -> a / b).by(outV().outE("knows").count()).
+                inV().
+                inE("knows").<Double,Long>sack((a, b) -> a / b).by(inV().inE("knows").count()).
+                outV().
+                barrier().dedup().sack();
         System.out.println(traversal);
         traversal.forEachRemaining(System.out::println);
         System.out.println(traversal);
@@ -181,12 +183,12 @@ public class TinkerGraphTest {
     @Ignore
     public void testPlay5() throws Exception {
         TinkerGraph graph = TinkerGraph.open();
-        graph.createIndex("name",Vertex.class);
+        graph.createIndex("name", Vertex.class);
         graph.io(GraphMLIo.build()).readGraph("/Users/marko/software/tinkerpop/tinkerpop3/data/grateful-dead.xml");
         GraphTraversalSource g = graph.traversal(GraphTraversalSource.computer());
 
-        final Supplier<Traversal<?,?>> traversal = () ->
-                g.V().repeat(out()).times(5).as("a").out("writtenBy").as("b").select("a","b").count();
+        final Supplier<Traversal<?, ?>> traversal = () ->
+                g.V().repeat(out()).times(5).as("a").out("writtenBy").as("b").select("a", "b").count();
 
         System.out.println(traversal.get());
         System.out.println(traversal.get().iterate());