What prevents me from wrapping stable types from the Motoko base library in a OOP way using a ref on the stable type?

Sorry the question might not be very clear, let me explain: I recently learnt that by using stable records that have a var member inside it, when that record is passed to functions, the inner var member is handled by motoko as a reference, and hence it is possible to update a stable var inside a function. By example:

// In my canister
stable let my_wrapped_var = { var inner = "foo"; };

func updateMyVar(my_wrapped_var: MyWrappedVar) { 
  my_wrapped_var.inner := "bar"; // This updates the variable in stable memory

This example is quite simple, but I was experimenting doing a module like this for a TrieClass:

type WrappedRef<T> = { var ref: T; };
public func init<T>(t : T) : WrappedRef<T>{
    var ref = t;

type Trie<K, V> = Trie.Trie<K, V>;
type Key<K> = Trie.Key<K>;

public class TrieClass<K, V>(
  trie_: WrappedRef<Trie<K, V>>,
  key_gen: (K) -> Key<K>,
  key_eq: (K, K) -> Bool
) {

  // Wrapping all Trie functions...

  public func put(k: K, v: V) : ?V {
    let (trie, old_v) = Trie.put(trie_.ref, key_gen(k), key_eq, v);
    trie_.ref        := trie;

  public func get(k: K) : ?V {
    Trie.get(trie_.ref, key_gen(k), key_eq);

  public func remove(k: K) : ?V {
    let (trie, old_v) = Trie.remove(trie_.ref, key_gen(k), key_eq);
    trie_.ref        := trie;


Then in my canister:

  stable let trie_ref = WrappedRef.init(Trie.empty<Nat32, Text>());

  let trie = TrieClass.TrieClass<Nat32, Text>(trie_ref, keyNat32, Nat32.equal);

  // perform updates on the trie in OOP way, directly in stable memory!
  trie.put(0, "hello");
  // etc.

Is there any inconvenient in doing this ?

1 Like