Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 6cfb8a2

Browse files
committed
Add pop functions
1 parent 8460f3d commit 6cfb8a2

File tree

4 files changed

+39
-11
lines changed

4 files changed

+39
-11
lines changed

src/Data/Map.purs

+17-11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Data.Map
1616
, fromList
1717
, fromListWith
1818
, delete
19+
, pop
1920
, member
2021
, alter
2122
, update
@@ -34,7 +35,7 @@ import Data.List (List(..), length, nub)
3435
import Data.Maybe (Maybe(..), maybe, isJust)
3536
import Data.Monoid (class Monoid)
3637
import Data.Traversable (traverse, class Traversable)
37-
import Data.Tuple (Tuple(..), uncurry)
38+
import Data.Tuple (Tuple(..), uncurry, snd)
3839

3940
import Partial.Unsafe (unsafePartial)
4041

@@ -195,21 +196,26 @@ insert = down Nil
195196
ThreeMiddle a k1 v1 k2 v2 d, KickUp b k v c -> up ctx (KickUp (Two a k1 v1 b) k v (Two c k2 v2 d))
196197
ThreeRight a k1 v1 b k2 v2, KickUp c k v d -> up ctx (KickUp (Two a k1 v1 b) k2 v2 (Two c k v d))
197198

198-
-- | Delete a key and its corresponding value from a map
199+
-- | Delete a key and its corresponding value from a map.
199200
delete :: forall k v. Ord k => k -> Map k v -> Map k v
200-
delete = down Nil
201+
delete k m = maybe m snd (pop k m)
202+
203+
-- | Delete a key and its corresponding value from a map, returning the value
204+
-- | as well as the subsequent map.
205+
pop :: forall k v. Ord k => k -> Map k v -> Maybe (Tuple v (Map k v))
206+
pop = down Nil
201207
where
202208
comp :: k -> k -> Ordering
203209
comp = compare
204210

205-
down :: List (TreeContext k v) -> k -> Map k v -> Map k v
211+
down :: List (TreeContext k v) -> k -> Map k v -> Maybe (Tuple v (Map k v))
206212
down = unsafePartial \ctx k m -> case m of
207-
Leaf -> fromZipper ctx Leaf
213+
Leaf -> Nothing
208214
Two left k1 v1 right ->
209215
case right, comp k k1 of
210-
Leaf, EQ -> up ctx Leaf
216+
Leaf, EQ -> Just (Tuple v1 (up ctx Leaf))
211217
_ , EQ -> let max = maxNode left
212-
in removeMaxNode (Cons (TwoLeft max.key max.value right) ctx) left
218+
in Just (Tuple v1 (removeMaxNode (Cons (TwoLeft max.key max.value right) ctx) left))
213219
_ , LT -> down (Cons (TwoLeft k1 v1 right) ctx) k left
214220
_ , _ -> down (Cons (TwoRight left k1 v1) ctx) k right
215221
Three left k1 v1 mid k2 v2 right ->
@@ -218,12 +224,12 @@ delete = down Nil
218224
Leaf, Leaf, Leaf -> true
219225
_ , _ , _ -> false
220226
in case leaves, comp k k1, comp k k2 of
221-
true, EQ, _ -> fromZipper ctx (Two Leaf k2 v2 Leaf)
222-
true, _ , EQ -> fromZipper ctx (Two Leaf k1 v1 Leaf)
227+
true, EQ, _ -> Just (Tuple v1 (fromZipper ctx (Two Leaf k2 v2 Leaf)))
228+
true, _ , EQ -> Just (Tuple v2 (fromZipper ctx (Two Leaf k1 v1 Leaf)))
223229
_ , EQ, _ -> let max = maxNode left
224-
in removeMaxNode (Cons (ThreeLeft max.key max.value mid k2 v2 right) ctx) left
230+
in Just (Tuple v1 (removeMaxNode (Cons (ThreeLeft max.key max.value mid k2 v2 right) ctx) left))
225231
_ , _ , EQ -> let max = maxNode mid
226-
in removeMaxNode (Cons (ThreeMiddle left k1 v1 max.key max.value right) ctx) mid
232+
in Just (Tuple v2 (removeMaxNode (Cons (ThreeMiddle left k1 v1 max.key max.value right) ctx) mid))
227233
_ , LT, _ -> down (Cons (ThreeLeft k1 v1 mid k2 v2 right) ctx) k left
228234
_ , GT, LT -> down (Cons (ThreeMiddle left k1 v1 k2 v2 right) ctx) k mid
229235
_ , _ , _ -> down (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) k right

src/Data/StrMap.purs

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Data.StrMap
1818
, fromList
1919
, fromListWith
2020
, delete
21+
, pop
2122
, member
2223
, alter
2324
, update
@@ -174,6 +175,11 @@ foreign import _unsafeDeleteStrMap :: forall a. Fn2 (StrMap a) String (StrMap a)
174175
delete :: forall a. String -> StrMap a -> StrMap a
175176
delete k = mutate (\s -> SM.delete s k)
176177

178+
-- | Delete a key and value from a map, returning the value
179+
-- | as well as the subsequent map
180+
pop :: forall a. String -> StrMap a -> Maybe (Tuple a (StrMap a))
181+
pop k m = lookup k m <#> \a -> Tuple a (delete k m)
182+
177183
-- | Insert, remove or update a value for a key in a map
178184
alter :: forall a. (Maybe a -> Maybe a) -> String -> StrMap a -> StrMap a
179185
alter f k m = case f (k `lookup` m) of

test/Test/Data/Map.purs

+8
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ mapTests = do
125125
quickCheck $ \k v -> M.isEmpty (M.delete (smallKey k) (M.insert k (number v) M.empty))
126126
<?> ("k: " <> show k <> ", v: " <> show v)
127127

128+
log "Test pop after inserting"
129+
quickCheck $ \k v -> M.pop (smallKey k) (M.insert k (number v) M.empty) == Just (Tuple v M.empty)
130+
<?> ("k: " <> show k <> ", v: " <> show v)
131+
132+
log "Pop non-existent key"
133+
quickCheck $ \k1 k2 v -> k1 == k2 || M.pop (smallKey k2) (M.insert k1 (number v) M.empty) == Nothing
134+
<?> ("k1: " <> show k1 <> ", k2: " <> show k2 <> ", v: " <> show v)
135+
128136
log "Insert two, lookup first"
129137
quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k1 (M.insert (smallKey k2) (number v2) (M.insert (smallKey k1) (number v1) M.empty)) == Just v1
130138
<?> ("k1: " <> show k1 <> ", v1: " <> show v1 <> ", k2: " <> show k2 <> ", v2: " <> show v2)

test/Test/Data/StrMap.purs

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ strMapTests = do
6060
quickCheck $ \k v -> M.isEmpty (M.delete k (M.insert k (number v) M.empty))
6161
<?> ("k: " <> show k <> ", v: " <> show v)
6262

63+
log "Test pop after inserting"
64+
quickCheck $ \k v -> M.pop k (M.insert k (number v) M.empty) == Just (Tuple v M.empty)
65+
<?> ("k: " <> show k <> ", v: " <> show v)
66+
67+
log "Pop non-existent key"
68+
quickCheck $ \k1 k2 v -> k1 == k2 || M.pop k2 (M.insert k1 (number v) M.empty) == Nothing
69+
<?> ("k1: " <> show k1 <> ", k2: " <> show k2 <> ", v: " <> show v)
70+
6371
log "Insert two, lookup first"
6472
quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k1 (M.insert k2 (number v2) (M.insert k1 (number v1) M.empty)) == Just v1
6573
<?> ("k1: " <> show k1 <> ", v1: " <> show v1 <> ", k2: " <> show k2 <> ", v2: " <> show v2)

0 commit comments

Comments
 (0)