Currently, Traverser.bulk() is a long. This should be generalized to support any type of "bulk" that can be split, merged, and has a magnitude, where our current representation would be a LongBulk.
There are three reasons to support this.
1. Right now we use Traverser.sack() to handle "energy flows" (0/0 to 1.0 energy in a traverser). We have introduced this ugly TraversalSource.withBulk(false) to allow these to semantically make sense (i.e. remain unitary). The "energy" should be the "bulk" as it can be split, merged, and has a magnitude.
2. We can support complex numbers for bulks (and complex number arrays). There is currently no strong use case for this beyond quantum simulation and wave dynamics, but you never know what might unfold. A solid algorithm here would be epic.
3. We need to be able to support BigInteger as the bulking model on complex graphs easily blows long. There have been numerous times where I wanted to repeat() more times, but can't without incurring long overflow and thus, negative bulk. If the computation calls for it, a user should be able to use BigInteger.
Our current model would be:
Another benefit of this is that bulking is now decoupled from the Traverser class and thus, you would be able to use different bulk classes with the same Traverser-species:
...where the default is assumed LongBulk and thus, you don't have to specify a withBulk. For backwards compatible sake, withBulk(false) would simply be IdentityLongBulk would would just return a 1 for everything.
We will want to then expose it.bulk() methods so algorithms can alter the bulk as they see fit. However, this is where a backwards compatibility issue would happen. Traverser.bulk() -> Bulk and Traverser.magnitude() -> Number (sidenote ---- perhaps "magnitude" is just called "count").
What is stellar about this is that it frees up "sack" for more "objects" and not for "bulking" when long is not sufficient. Thus, we promote that "sack" is for objects and "bulk" is for, well, bulk! Now we no longer have this weird tension between bulk and sack as they have two different uses. Bulking is for altering the "magnitude" of a traverser and sacking if for gathering statistics/data about the graph along the way.