When used like this - there will never be an Operational.updates() fired for the initial value of cScene right? it's only from the second value (first change) and on?
That's correct. I had a similar problem come up in my day job. I had a set of network configurations that could change over time. I wanted to detect all additions and removals from the set, but during initialization of the program - which is wrapped in a big transaction - there could have been items added to the set. To make sure I caught all changes from the beginning of the program, I wrote this helper function (C++ version of Sodium). If I give it an empty set as the initial value a, then the first output value is the delta of initial value of ca and the empty set. The point of having well-defined semantics is that what this function will do is 100% predictable, and it'll work on all version of Sodium.
/*!
* When the cell changes, give deltas between old and new values. The first delta
* is between a specified initial value and the cell's first value. The first
* value of a hold is defined as any event held in the first transaction, or,
* failing that, the default value passed to hold.
*
* The function f receives the arguments (update value, previous value).
*/
template <typename A, typename Fn>
sodium::stream<typename std::result_of<Fn(A,A)>::type> deltas_with_initial(const sodium::cell<A>& ca, const A& a,
const Fn& f)
{
using namespace sodium;
transaction trans;
stream<A> sValue = ca.value();
cell<A> previous = sValue.hold(a);
auto sOut = sValue.snapshot(previous, f);
trans.close();
return sOut;
}