Skip to content

Commit 1059d3c

Browse files
committed
Optimize Strict.alter
1 parent b6bde46 commit 1059d3c

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

Data/HashMap/Internal.hs

+5
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ module Data.HashMap.Internal
128128
, equalKeys1
129129
, lookupRecordCollision
130130
, LookupRes(..)
131+
, lookupResToMaybe
131132
, insert'
132133
, delete'
133134
, lookup'
@@ -613,6 +614,10 @@ lookup' h k m = case lookupRecordCollision# h k m of
613614
-- If a collision did not occur then it will have the Int value (-1).
614615
data LookupRes a = Absent | Present a !Int
615616

617+
lookupResToMaybe :: LookupRes a -> Maybe a
618+
lookupResToMaybe Absent = Nothing
619+
lookupResToMaybe (Present x _) = Just x
620+
616621
-- Internal helper for lookup. This version takes the precomputed hash so
617622
-- that functions that make multiple calls to lookup and related functions
618623
-- (insert, delete) only need to calculate the hash once.

Data/HashMap/Internal/Strict.hs

+12-3
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,18 @@ update f = alter (>>= f)
305305
-- @
306306
alter :: (Eq k, Hashable k) => (Maybe v -> Maybe v) -> k -> HashMap k v -> HashMap k v
307307
alter f k m =
308-
case f (HM.lookup k m) of
309-
Nothing -> HM.delete k m
310-
Just v -> insert k v m
308+
let !h = hash k
309+
!lookupRes = HM.lookupRecordCollision h k m
310+
in case f (HM.lookupResToMaybe lookupRes) of
311+
Nothing -> case lookupRes of
312+
Absent -> m
313+
Present _ collPos -> HM.deleteKeyExists collPos h k m
314+
Just !v' -> case lookupRes of
315+
Absent -> HM.insertNewKey h k v' m
316+
Present !v collPos ->
317+
if v `ptrEq` v'
318+
then m
319+
else HM.insertKeyExists collPos h k v' m
311320
{-# INLINABLE alter #-}
312321

313322
-- | /O(log n)/ The expression (@'alterF' f k map@) alters the value @x@ at

0 commit comments

Comments
 (0)