Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

m-renaud
What
====

Rename unordered-container's Data.HashMap.lookupDefault to findWithDefault.

findWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v

Note: There are no functionality changes, this is purely a rename.


Why
===

This aligns the Data.HashMap API with containers' Data.Map.findWithDefault.

Data.Map.findWithDefault :: Ord k => a -> k -> Map k a -> a

The map APIs provided by the two packages are almost drop in replacement compatible if you aren't using any of the implementation specific functions (like ordering based functions from Data.Map), this change brings us one step closer.

API consistency reduces the cognitive overhead when learning a new package. Having to learn different function names for the same functionality depending on which "map" implementation you're using is a poor developer experience.

We chose the containers' name findWithDefault over unordered-containers' lookupDefault for two reasons:
  1. Existing lookupX functions returns a Maybe value, while findX functions return a non-wrapped value.
  2. The containers package ships with GHC and is a "core" package.

Pros:
-----

- Consistent API between different "map" implementations (Data.Map, Data.IntMap, Data.HashMap). This makes switching implementations an import change.
- Naming matches other similar functions (lookupX return Maybe-wrapped values)

Cons:
-----

- API change requires users to update their code
  + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)


How
===


Code Changes:
-------------

- Rename the function in Data.HashMap.Base (and expose it from Strict and Lazy modules)
- Make lookupDefault an INLINE alias of findWithDefault
- Add DEPRECATION notice to lookupDefault
- Bump unordered-containers version to 0.2.9.0


Migration - Option 1:
---------------------

Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault with deprecation notice remains for 1 year (subject to change)
- after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major version bump due to breaking change)

Migration - Option 2:
---------------------

- Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault function is never removed


Discussion: 
===========

I would like to get some comments on this proposal. In particular: 
- Is the small API churn worth the increase in consistency?
- Should migration option 1 (completely remove the old function) or 2 (keep old function indefinitely) be taken? We can punt on this and go with option 2 to start and revisit later if desired.

I hope a decision about the proposal can be reached by 2018-02-09. Thanks!





_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

Ivan Lazar Miljenovic
On 24 January 2018 at 13:14, Matt Renaud <[hidden email]> wrote:

> What
> ====
>
> Rename unordered-container's Data.HashMap.lookupDefault to findWithDefault.
>
> findWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v
>
> Note: There are no functionality changes, this is purely a rename.
>
>
> Why
> ===
>
> This aligns the Data.HashMap API with containers' Data.Map.findWithDefault.
>
> Data.Map.findWithDefault :: Ord k => a -> k -> Map k a -> a
>
> The map APIs provided by the two packages are almost drop in replacement
> compatible if you aren't using any of the implementation specific functions
> (like ordering based functions from Data.Map), this change brings us one
> step closer.
>
> API consistency reduces the cognitive overhead when learning a new package.
> Having to learn different function names for the same functionality
> depending on which "map" implementation you're using is a poor developer
> experience.
>
> We chose the containers' name findWithDefault over unordered-containers'
> lookupDefault for two reasons:
>
> Existing lookupX functions returns a Maybe value, while findX functions
> return a non-wrapped value.
> The containers package ships with GHC and is a "core" package.
>
>
> Pros:
> -----
>
> - Consistent API between different "map" implementations (Data.Map,
> Data.IntMap, Data.HashMap). This makes switching implementations an import
> change.
> - Naming matches other similar functions (lookupX return Maybe-wrapped
> values)
>
> Cons:
> -----
>
> - API change requires users to update their code
>   + unordered-containers has A LOT of users: 358815 total (13325 in the last
> 30 days)
>
>
> How
> ===
>
> https://github.com/tibbe/unordered-containers/pull/176/commits/152f8818ee13dacb370e49b904edc4c1a4c8f87b
>
> Code Changes:
> -------------
>
> - Rename the function in Data.HashMap.Base (and expose it from Strict and
> Lazy modules)
> - Make lookupDefault an INLINE alias of findWithDefault
> - Add DEPRECATION notice to lookupDefault
> - Bump unordered-containers version to 0.2.9.0
>
>
> Migration - Option 1:
> ---------------------
>
> - Announce on Haskell communication channels (haskell-cafe@,
> haskell-community@, #haskell on Twitter, Reddit thread, etc.)
> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated
> function
> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
> - lookupDefault with deprecation notice remains for 1 year (subject to
> change)
> - after 1 year the lookupDefault function is removed, unordered-containers
> version bumped to 0.3.0.0 (major version bump due to breaking change)
>
> Migration - Option 2:
> ---------------------
>
> - Announce on Haskell communication channels (haskell-cafe@,
> haskell-community@, #haskell on Twitter, Reddit thread, etc.)
> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated
> function
> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
> - lookupDefault function is never removed
>
>
> Discussion:
> ===========
>
> I would like to get some comments on this proposal. In particular:
> - Is the small API churn worth the increase in consistency?
> - Should migration option 1 (completely remove the old function) or 2 (keep
> old function indefinitely) be taken? We can punt on this and go with option
> 2 to start and revisit later if desired.
>
> I hope a decision about the proposal can be reached by 2018-02-09. Thanks!

I prefer Option 1, but I think we need a release _without_ DEPRECATION
first, and then it can be added to lookupDefault (which currently
requires a major version bump per the PVP, though this might be
changing: https://github.com/haskell/pvp/issues/12 )

Whether this is worth it though is another story; until/unless we get
Backpack support on containers and unordered-containers (which also
requires adding a lot more functionality to the latter last I checked)
I think it's OK that they use different names.

--
Ivan Lazar Miljenovic
[hidden email]
http://IvanMiljenovic.wordpress.com
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

m-renaud
Thanks for the input!

I think we need a release _without_ DEPRECATION first...though this might be changing

Either works for me. Personally I'd like it to be removed eventually but I anticipate the timeline for that will be long, in which case having a minor release that doesn't deprecate it to start doesn't seem like it would cause any harm. Then we can wait until the PVP decision is worked out.

until/unless we get Backpack support on containers and unordered-containers

Yeah, this would make it a requirement that they share the same name, in the meantime its unfortunate that they don't have the same name. Obviously an extreme, but imagine if "fmap" was called something different by every functor instance :P Since the migration for users is very straightforward I'd argue the cost is pretty low to increase consistency.


On Tue, Jan 23, 2018 at 6:59 PM, Ivan Lazar Miljenovic <[hidden email]> wrote:
On 24 January 2018 at 13:14, Matt Renaud <[hidden email]> wrote:
> What
> ====
>
> Rename unordered-container's Data.HashMap.lookupDefault to findWithDefault.
>
> findWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v
>
> Note: There are no functionality changes, this is purely a rename.
>
>
> Why
> ===
>
> This aligns the Data.HashMap API with containers' Data.Map.findWithDefault.
>
> Data.Map.findWithDefault :: Ord k => a -> k -> Map k a -> a
>
> The map APIs provided by the two packages are almost drop in replacement
> compatible if you aren't using any of the implementation specific functions
> (like ordering based functions from Data.Map), this change brings us one
> step closer.
>
> API consistency reduces the cognitive overhead when learning a new package.
> Having to learn different function names for the same functionality
> depending on which "map" implementation you're using is a poor developer
> experience.
>
> We chose the containers' name findWithDefault over unordered-containers'
> lookupDefault for two reasons:
>
> Existing lookupX functions returns a Maybe value, while findX functions
> return a non-wrapped value.
> The containers package ships with GHC and is a "core" package.
>
>
> Pros:
> -----
>
> - Consistent API between different "map" implementations (Data.Map,
> Data.IntMap, Data.HashMap). This makes switching implementations an import
> change.
> - Naming matches other similar functions (lookupX return Maybe-wrapped
> values)
>
> Cons:
> -----
>
> - API change requires users to update their code
>   + unordered-containers has A LOT of users: 358815 total (13325 in the last
> 30 days)
>
>
> How
> ===
>
> https://github.com/tibbe/unordered-containers/pull/176/commits/152f8818ee13dacb370e49b904edc4c1a4c8f87b
>
> Code Changes:
> -------------
>
> - Rename the function in Data.HashMap.Base (and expose it from Strict and
> Lazy modules)
> - Make lookupDefault an INLINE alias of findWithDefault
> - Add DEPRECATION notice to lookupDefault
> - Bump unordered-containers version to 0.2.9.0
>
>
> Migration - Option 1:
> ---------------------
>
> - Announce on Haskell communication channels (haskell-cafe@,
> haskell-community@, #haskell on Twitter, Reddit thread, etc.)
> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated
> function
> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
> - lookupDefault with deprecation notice remains for 1 year (subject to
> change)
> - after 1 year the lookupDefault function is removed, unordered-containers
> version bumped to 0.3.0.0 (major version bump due to breaking change)
>
> Migration - Option 2:
> ---------------------
>
> - Announce on Haskell communication channels (haskell-cafe@,
> haskell-community@, #haskell on Twitter, Reddit thread, etc.)
> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated
> function
> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
> - lookupDefault function is never removed
>
>
> Discussion:
> ===========
>
> I would like to get some comments on this proposal. In particular:
> - Is the small API churn worth the increase in consistency?
> - Should migration option 1 (completely remove the old function) or 2 (keep
> old function indefinitely) be taken? We can punt on this and go with option
> 2 to start and revisit later if desired.
>
> I hope a decision about the proposal can be reached by 2018-02-09. Thanks!

I prefer Option 1, but I think we need a release _without_ DEPRECATION
first, and then it can be added to lookupDefault (which currently
requires a major version bump per the PVP, though this might be
changing: https://github.com/haskell/pvp/issues/12 )

Whether this is worth it though is another story; until/unless we get
Backpack support on containers and unordered-containers (which also
requires adding a lot more functionality to the latter last I checked)
I think it's OK that they use different names.

--
Ivan Lazar Miljenovic
[hidden email]
http://IvanMiljenovic.wordpress.com


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

Henning Thielemann
In reply to this post by m-renaud

On Tue, 23 Jan 2018, Matt Renaud wrote:

> Cons:
> -----
>
> - API change requires users to update their code
>   + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)

A better measure are certainly the reverse package dependencies:
    https://www.stackage.org/package/unordered-containers

There are almost 1000 packages that import unordered-containers, still
quite a lot!

> Migration - Option 1:
> ---------------------
>
> - Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit
> thread, etc.)
> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
> - lookupDefault with deprecation notice remains for 1 year (subject to change)
> - after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major
> version bump due to breaking change)
I'd say 1 year is too short. There is no need to remove the function
quickly. I'd vote for adding a deprecation warning soon, but then keep the
function until the next larger API overhaul or say, for five years or a
decade.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

Andreas Abel
 > I'd say 1 year is too short. There is no need to remove the function
 > quickly. I'd vote for adding a deprecation warning soon, but then keep
 > the function until the next larger API overhaul or say, for five years
 > or a decade.

+1.

Yes.

On 24.01.2018 08:11, Henning Thielemann wrote:

>
> On Tue, 23 Jan 2018, Matt Renaud wrote:
>
>> Cons:
>> -----
>>
>> - API change requires users to update their code
>>   + unordered-containers has A LOT of users: 358815 total (13325 in
>> the last 30 days)
>
> A better measure are certainly the reverse package dependencies:
>     https://www.stackage.org/package/unordered-containers
>
> There are almost 1000 packages that import unordered-containers, still
> quite a lot!
>
>> Migration - Option 1:
>> ---------------------
>>
>> - Announce on Haskell communication channels (haskell-cafe@,
>> haskell-community@, #haskell on Twitter, Reddit
>> thread, etc.)
>> - Users of unordered-containers >= 0.2.9.0 receive warning about
>> deprecated function
>> - Code can be updated by find and replace:
>> s/lookupDefault/findWithDefault/
>> - lookupDefault with deprecation notice remains for 1 year (subject to
>> change)
>> - after 1 year the lookupDefault function is removed,
>> unordered-containers version bumped to 0.3.0.0 (major
>> version bump due to breaking change)
>
> I'd say 1 year is too short. There is no need to remove the function
> quickly. I'd vote for adding a deprecation warning soon, but then keep
> the function until the next larger API overhaul or say, for five years
> or a decade.
>
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>


--
Andreas Abel  <><      Du bist der geliebte Mensch.

Department of Computer Science and Engineering
Chalmers and Gothenburg University, Sweden

[hidden email]
http://www.cse.chalmers.se/~abela/
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

m-renaud
> keep the function until the next larger API overhaul or say, for five years or a decade.

That sounds good to me, I wasn't sure how long is reasonable to wait after deprecating an API before removing it.

On Wed, Jan 24, 2018 at 6:25 AM, Andreas Abel <[hidden email]> wrote:
> I'd say 1 year is too short. There is no need to remove the function
> quickly. I'd vote for adding a deprecation warning soon, but then keep
> the function until the next larger API overhaul or say, for five years
> or a decade.

+1.

Yes.


On 24.01.2018 08:11, Henning Thielemann wrote:

On Tue, 23 Jan 2018, Matt Renaud wrote:

Cons:
-----

- API change requires users to update their code
  + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)

A better measure are certainly the reverse package dependencies:
    https://www.stackage.org/package/unordered-containers

There are almost 1000 packages that import unordered-containers, still quite a lot!

Migration - Option 1:
---------------------

- Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit
thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault with deprecation notice remains for 1 year (subject to change)
- after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major
version bump due to breaking change)

I'd say 1 year is too short. There is no need to remove the function quickly. I'd vote for adding a deprecation warning soon, but then keep the function until the next larger API overhaul or say, for five years or a decade.


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries



--
Andreas Abel  <><      Du bist der geliebte Mensch.

Department of Computer Science and Engineering
Chalmers and Gothenburg University, Sweden

[hidden email]
http://www.cse.chalmers.se/~abela/


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

amindfv
In reply to this post by Andreas Abel
Doesn't quickly adding a deprecation warning break building any of those 1000+ packages with -Werror?

I'd support adding the new function, but am very reluctant to force any quick changes.

Tom


> El 24 ene 2018, a las 09:25, Andreas Abel <[hidden email]> escribió:
>
> > I'd say 1 year is too short. There is no need to remove the function
> > quickly. I'd vote for adding a deprecation warning soon, but then keep
> > the function until the next larger API overhaul or say, for five years
> > or a decade.
>
> +1.
>
> Yes.
>
>> On 24.01.2018 08:11, Henning Thielemann wrote:
>>> On Tue, 23 Jan 2018, Matt Renaud wrote:
>>> Cons:
>>> -----
>>>
>>> - API change requires users to update their code
>>>   + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)
>> A better measure are certainly the reverse package dependencies:
>>    https://www.stackage.org/package/unordered-containers
>> There are almost 1000 packages that import unordered-containers, still quite a lot!
>>> Migration - Option 1:
>>> ---------------------
>>>
>>> - Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit
>>> thread, etc.)
>>> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
>>> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
>>> - lookupDefault with deprecation notice remains for 1 year (subject to change)
>>> - after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major
>>> version bump due to breaking change)
>> I'd say 1 year is too short. There is no need to remove the function quickly. I'd vote for adding a deprecation warning soon, but then keep the function until the next larger API overhaul or say, for five years or a decade.
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Department of Computer Science and Engineering
> Chalmers and Gothenburg University, Sweden
>
> [hidden email]
> http://www.cse.chalmers.se/~abela/
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

m-renaud
> Doesn't quickly adding a deprecation warning break building any of those 1000+ packages with -Werror?

It appears that https://github.com/haskell/pvp/issues/12 is close to being resolved[1], and as hvr mentioned Hackage already prevents packages with -Werror from being uploaded, so this shouldn't be an issue for packages already uploaded. But yes, if someone is using unordered-containers and building locally with -Werror then the build would fail.

That being said, if the plan is to deprecate it then I don't think there's a better way than marking it DEPRECATED. We could go with a "soft" deprecation--remove function comments and replace with "This function is deprecated, use findWithDefault" and make some announcements--but I doubt many people would act on that so it would just be kicking the can down the road.

I'd support adding the new function, but am very reluctant to force any quick changes.

Glad to hear! It would be nice if there was a way of getting information about how often this particular function was used so we could get a better estimate of how many packages would truly be affected. And I completely agreed that we should do everything we can to not break people's builds, but hopefully not at the expense of improving APIs.

On Wed, Jan 24, 2018 at 3:25 PM, <[hidden email]> wrote:
Doesn't quickly adding a deprecation warning break building any of those 1000+ packages with -Werror?

I'd support adding the new function, but am very reluctant to force any quick changes.

Tom


> El 24 ene 2018, a las 09:25, Andreas Abel <[hidden email]> escribió:
>
> > I'd say 1 year is too short. There is no need to remove the function
> > quickly. I'd vote for adding a deprecation warning soon, but then keep
> > the function until the next larger API overhaul or say, for five years
> > or a decade.
>
> +1.
>
> Yes.
>
>> On 24.01.2018 08:11, Henning Thielemann wrote:
>>> On Tue, 23 Jan 2018, Matt Renaud wrote:
>>> Cons:
>>> -----
>>>
>>> - API change requires users to update their code
>>>   + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)
>> A better measure are certainly the reverse package dependencies:
>>    https://www.stackage.org/package/unordered-containers
>> There are almost 1000 packages that import unordered-containers, still quite a lot!
>>> Migration - Option 1:
>>> ---------------------
>>>
>>> - Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit
>>> thread, etc.)
>>> - Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
>>> - Code can be updated by find and replace: s/lookupDefault/findWithDefault/
>>> - lookupDefault with deprecation notice remains for 1 year (subject to change)
>>> - after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major
>>> version bump due to breaking change)
>> I'd say 1 year is too short. There is no need to remove the function quickly. I'd vote for adding a deprecation warning soon, but then keep the function until the next larger API overhaul or say, for five years or a decade.
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>
> --
> Andreas Abel  <><      Du bist der geliebte Mensch.
>
> Department of Computer Science and Engineering
> Chalmers and Gothenburg University, Sweden
>
> [hidden email]
> http://www.cse.chalmers.se/~abela/
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

David Feuer
In reply to this post by m-renaud
I'm wondering if we should ultimately get rid of that function altogether, from both packages. From an API design standpoint, it's kind of silly, because

    findWithDefault d k m =
       fromMaybe d (lookup k m)

At present, there's a slight performance penalty to doing it that way. I wonder if we can squash that now that GHC has unboxed sums.

    lookup# :: ... => k -> m a -> (# (# #) | a #)
    lookup k m = case lookup# k m of
      (# _ | #) -> Nothing
      (# | a #) -> Just a

Now case-of-case will get rid of the extra Maybe.


On Jan 23, 2018 9:15 PM, "Matt Renaud" <[hidden email]> wrote:
What
====

Rename unordered-container's Data.HashMap.lookupDefault to findWithDefault.

findWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v

Note: There are no functionality changes, this is purely a rename.


Why
===

This aligns the Data.HashMap API with containers' Data.Map.findWithDefault.

Data.Map.findWithDefault :: Ord k => a -> k -> Map k a -> a

The map APIs provided by the two packages are almost drop in replacement compatible if you aren't using any of the implementation specific functions (like ordering based functions from Data.Map), this change brings us one step closer.

API consistency reduces the cognitive overhead when learning a new package. Having to learn different function names for the same functionality depending on which "map" implementation you're using is a poor developer experience.

We chose the containers' name findWithDefault over unordered-containers' lookupDefault for two reasons:
  1. Existing lookupX functions returns a Maybe value, while findX functions return a non-wrapped value.
  2. The containers package ships with GHC and is a "core" package.

Pros:
-----

- Consistent API between different "map" implementations (Data.Map, Data.IntMap, Data.HashMap). This makes switching implementations an import change.
- Naming matches other similar functions (lookupX return Maybe-wrapped values)

Cons:
-----

- API change requires users to update their code
  + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)


How
===


Code Changes:
-------------

- Rename the function in Data.HashMap.Base (and expose it from Strict and Lazy modules)
- Make lookupDefault an INLINE alias of findWithDefault
- Add DEPRECATION notice to lookupDefault
- Bump unordered-containers version to 0.2.9.0


Migration - Option 1:
---------------------

Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault with deprecation notice remains for 1 year (subject to change)
- after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major version bump due to breaking change)

Migration - Option 2:
---------------------

- Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault function is never removed


Discussion: 
===========

I would like to get some comments on this proposal. In particular: 
- Is the small API churn worth the increase in consistency?
- Should migration option 1 (completely remove the old function) or 2 (keep old function indefinitely) be taken? We can punt on this and go with option 2 to start and revisit later if desired.

I hope a decision about the proposal can be reached by 2018-02-09. Thanks!





_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries



_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Rename HashMap.lookupDefault to HashMap.findWithDefault

m-renaud
I'm wondering if we should ultimately get rid of that function altogether, from both packages

I'm on the fence about this one since its such a common operation, I personally would be a little surprised if it wasn't part of the API. You're right that it's not /that/ much code to write, but I imagine everyone will end up writing their own findWithDefault in their codebase, I may be wrong though.


On Wed, Jan 24, 2018 at 4:27 PM, David Feuer <[hidden email]> wrote:
I'm wondering if we should ultimately get rid of that function altogether, from both packages. From an API design standpoint, it's kind of silly, because

    findWithDefault d k m =
       fromMaybe d (lookup k m)

At present, there's a slight performance penalty to doing it that way. I wonder if we can squash that now that GHC has unboxed sums.

    lookup# :: ... => k -> m a -> (# (# #) | a #)
    lookup k m = case lookup# k m of
      (# _ | #) -> Nothing
      (# | a #) -> Just a

Now case-of-case will get rid of the extra Maybe.


On Jan 23, 2018 9:15 PM, "Matt Renaud" <[hidden email]> wrote:
What
====

Rename unordered-container's Data.HashMap.lookupDefault to findWithDefault.

findWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v

Note: There are no functionality changes, this is purely a rename.


Why
===

This aligns the Data.HashMap API with containers' Data.Map.findWithDefault.

Data.Map.findWithDefault :: Ord k => a -> k -> Map k a -> a

The map APIs provided by the two packages are almost drop in replacement compatible if you aren't using any of the implementation specific functions (like ordering based functions from Data.Map), this change brings us one step closer.

API consistency reduces the cognitive overhead when learning a new package. Having to learn different function names for the same functionality depending on which "map" implementation you're using is a poor developer experience.

We chose the containers' name findWithDefault over unordered-containers' lookupDefault for two reasons:
  1. Existing lookupX functions returns a Maybe value, while findX functions return a non-wrapped value.
  2. The containers package ships with GHC and is a "core" package.

Pros:
-----

- Consistent API between different "map" implementations (Data.Map, Data.IntMap, Data.HashMap). This makes switching implementations an import change.
- Naming matches other similar functions (lookupX return Maybe-wrapped values)

Cons:
-----

- API change requires users to update their code
  + unordered-containers has A LOT of users: 358815 total (13325 in the last 30 days)


How
===


Code Changes:
-------------

- Rename the function in Data.HashMap.Base (and expose it from Strict and Lazy modules)
- Make lookupDefault an INLINE alias of findWithDefault
- Add DEPRECATION notice to lookupDefault
- Bump unordered-containers version to 0.2.9.0


Migration - Option 1:
---------------------

Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault with deprecation notice remains for 1 year (subject to change)
- after 1 year the lookupDefault function is removed, unordered-containers version bumped to 0.3.0.0 (major version bump due to breaking change)

Migration - Option 2:
---------------------

- Announce on Haskell communication channels (haskell-cafe@, haskell-community@, #haskell on Twitter, Reddit thread, etc.)
- Users of unordered-containers >= 0.2.9.0 receive warning about deprecated function
- Code can be updated by find and replace: s/lookupDefault/findWithDefault/
- lookupDefault function is never removed


Discussion: 
===========

I would like to get some comments on this proposal. In particular: 
- Is the small API churn worth the increase in consistency?
- Should migration option 1 (completely remove the old function) or 2 (keep old function indefinitely) be taken? We can punt on this and go with option 2 to start and revisit later if desired.

I hope a decision about the proposal can be reached by 2018-02-09. Thanks!





_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries




_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries