What I've observed in the Java version, is that the ranks can change during a transaction, which leads to all entries being removed then reinserted into the priority queue to keep updates occurring in the correct order.
This is really needed just for StreamLoop
, because you do not know what the rank is ment to be until the call to loop
.
Another thing about ranks is that they are not allowed to cycle. However references to sodium objects are allowed to cycle.
E.g.
StreamLoop<Integer> sl = new StreamLoop<>();
Stream<Integer> sOut = sl.map(x -> x + 1);
sl.loop(sOut);
Has a rank-cycle, and is not allowed as its rank will spiral up to infinity. (not an infinite loop currently because there is a visited
set in the code to stop that)
So how about ranks as Expressions, rather than Integers. So that a rank-cycle can be detected at run-time and an Exception can be thrown. Also ranks as Expressions can be evaluated late when the rank is really needed, so that the priority queue does not need to be cleared then refilled.
data RankExp
= RE_Max RankExp RankExp
| RE_Plus RankExp Int
| RE_Const Int
| RE_Var Ident
RE_Var
gets used to point to a rank which might not yet be known, and can be obtained later. Such as StreamLoop
before loop
is called.
I know what Java does at the moment works, and "If it ain't broken, why fix it?". But just seems like it could be done a little cleaner.
On second thought a memoized lazy integer for the rank would do too. And simply throw an Exception if the rank is evaluated too soon.