public bool TryGetValue(K key, out V value)
        {
            KvpNode <K, V> current = root;

            while (!current.IsNil)
            {
                int comparison = _comparer.Compare(key, current.Payload.Key);
                if (comparison < 0)
                {
                    current = current.Left;
                }
                else if (comparison > 0)
                {
                    current = current.Right;
                }
                else
                {
                    value = current.Payload.Value;
                    return(true);
                }
            }

            value = default;
            return(false);
        }
 public Descent Descend()
 {
     if (_current.IsNil)
     {
         return(_policy == NodeLocationPolicy.NoInsert ? Descent.NotFound : Descent.Found);
     }
     else
     {
         int comparison = _comparer.Compare(_targetKey, _current.Payload.Key);
         if (comparison < 0)
         {
             _current = _current.Left;
             return(Descent.Left);
         }
         else if (comparison > 0)
         {
             _current = _current.Right;
             return(Descent.Right);
         }
         else
         {
             return(_policy == NodeLocationPolicy.NoUpdate ? Descent.NotFound : Descent.Found);
         }
     }
 }
 public NodeLocator(
     K targetKey, IComparer <K> comparer, NodeLocationPolicy policy, KvpNode <K, V> root)
 {
     _targetKey = targetKey;
     _comparer  = comparer;
     _policy    = policy;
     _current   = root;
 }
        public IPerststentMap <K, V> Put(K key, V value, out Maybe <V> oldValue)
        {
            KeyValuePair <K, V> kvp     = new KeyValuePair <K, V>(key, value);
            NodeLocator         locator = new NodeLocator(key, _comparer, NodeLocationPolicy.Default, root);
            KvpNode <K, V>      newRoot = DoInsertOrUpdate(kvp, _ => kvp, locator);

            if (locator.CurrentNode.IsNil) // insertion
            {
                oldValue = Maybe <V> .Nothing;
                return(new PersistentMap <K, V>(newRoot, Count + 1, _comparer));
            }
            else // update
            {
                oldValue = new Maybe <V>(locator.CurrentNode.Payload.Value);
                return(new PersistentMap <K, V>(newRoot, Count, _comparer));
            }
        }
        public bool ContainsKey(K key)
        {
            KvpNode <K, V> current = root;

            while (!current.IsNil)
            {
                int comparison = _comparer.Compare(key, current.Payload.Key);
                if (comparison < 0)
                {
                    current = current.Left;
                }
                else if (comparison > 0)
                {
                    current = current.Right;
                }
                else
                {
                    return(true);
                }
            }

            return(false);
        }
 private PersistentMap(KvpNode <K, V> root, int count, IComparer <K> comparer) : base(root)
 {
     Count     = count;
     _comparer = comparer;
 }
 public IPerststentMap <K, V> PutIfAbsent(K key, V value)
 {
     KeyValuePair <K, V> kvp     = new KeyValuePair <K, V>(key, value);
     NodeLocator         locator = new NodeLocator(key, _comparer, NodeLocationPolicy.NoUpdate, root);
     // the update calculation is not executed
     KvpNode <K, V> newRoot = DoInsertOrUpdate(kvp, _ => default, locator);
 public KvpNode(KeyValuePair <K, V> kvp, KvpNode <K, V> left, KvpNode <K, V> right)
     : base(left, right)
 {
     Payload = kvp;
 }