I’m using RBTree from the “base” package and I have a couple of questions.
There is also an “OrderedMap” which seems to be based on the same RBTree, but persisted in stable memory. If I use EOP, should I use this “OrderedMap” version or it is fine to use regular RBTree?
I need an ability to get the next/previous existing key, when the key I’m trying to find does not exist. In terms of RBTree it would probably be the key of the parent node. How can I achieve that? If I can’t what would you suggest to use instead? I have a collection of kv-entries which are arranged in a linked list, but I also need an efficient search by key.
OderedMap is meant to be a replacement for RBTree. It’s a bit more efficient uses a little less memory (fewer indirections) and avoids using a class so the tree can be directly stored in a stable variable. The RBTree is still there for legacy users. Both should work for eop, but using RBTree probably requires a pre-upgrade hook to extract the tree, while OrderedMap does not.
Both the trees are not stored in stable memory but just ordinary heap data structures. The underlying tree can be stored in stable variables, with our without eop.
I don’t think either tree provides the function you are looking for but you could probably write it fairly easily yourself. Both trees are just ordered binary tree.
The new base library also provides pure/Map which is derived from OrderedMap (same representation, but slightly different API). In future, migrating from OrderedMap to pure/Map should be easier since you can just re-use the same data unchanged. So OrderedMap is more future proof.
Hm… I thought the whole promise of EOP was that I define whatever the state I want (including using any data-structure I want) then I simply attach it to a stable variable inside an actor and the allocator just stores it in stable memory instead of heap.
But you say that for some reason I can’t use classes (??? which are just sugar around objects) and that I still have to encode it and store directly in stable memory.
What’s the point then? Is there any documentation on what is the exact runtime behaviour for EOP and how to use old libraries with it?
About the pure/Map: seems like it’s undocumented. Could you please provide an example of how to do that?
That depends on what you do in pre_upgrade/post_upgrade. But as of now, EOP does not change whether you need pre/post_upgrade or not. EOP still only persists those variables the are declared stable. If you have a type that can’t be declared stable and you want to persist it then you still need pre/post_upgrade to, for example, copy the data to a stable type inside pre_upgrade and read the data from a stable type inside post_upgrade. For classes this is often done with share/unshare functions. As of now, classes with functions can’t be declared stable (with or without EOP), hence you still need pre/post_upgrade. This might change in the future.
There are of course other uses of pre/post_upgrade. Those functions can contain arbitrary code. So there will always be use for them.
I just stumbled across a talk and slides I gave on EOP, if that helps any. Most if not all of the material is due to @luc-blaeser, but he was busy so I gave the talk: