[Proposal] Keyword.fetch!/3 and Map.fetch!/3

34 vues
Accéder directement au premier message non lu

Paweł Urbanek

non lue,
26 janv. 2021, 03:38:1326/01/2021
à elixir-lang-core

I'd like to propose extending the API for Keyword and Map, fetch! method:

Map.fetch!(%{a: 1}, :b, 2) => 2
Keyword.fetch!([a: 1], :b, 2) => 2

Third argument represents value which will be returned in case the requested key is missing. Optionally maybe it could also accept the function which is executed only in case the key is missing and it's return value is used.

It would allow a simple way to fallback to default option values.

Adam Lancaster

non lue,
26 janv. 2021, 03:40:1326/01/2021
à elixir-l...@googlegroups.com
Hello,

There is Map.get/3 already, how would this differ?

Best

Adam

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/616a2726-740d-4b10-a02c-2a0c4e195a2fn%40googlegroups.com.

Paweł Urbanek

non lue,
26 janv. 2021, 03:47:0026/01/2021
à elixir-lang-core
Looks like get does not evaluate the fallback function:

Keyword.get([{:a, 1}], :b, fn () -> 2 + 2 end) => #Function<45.97283095/0 in :erl_eval.expr/5>

Maybe fetch!/3 could work like that?

Keyword.fetch!([{:a, 1}], :b, fn () -> 2 + 2 end) => 4

jean.pa...@gmail.com

non lue,
26 janv. 2021, 03:48:2326/01/2021
à elixir-l...@googlegroups.com
Hello,
I think you're looking for `.get_lazy/3` functions.

Best regards,
Jean

Paweł Urbanek

non lue,
26 janv. 2021, 03:53:0226/01/2021
à elixir-lang-core
Thanks, I was not aware of that.

Jonathan Arnett

non lue,
26 janv. 2021, 16:50:1526/01/2021
à elixir-l...@googlegroups.com

One potential benefit to a Map.fetch/3 command that wasn't considered is that it could help users define more specific error types. There's a loose convention to use {:ok, val} | :error | {:error, reason} as a "result" type in Elixir (analogous to Rust's Option and Result or Haskell's Maybe and Either). Map.fetch/3 conforms to this by returning {:ok, val} | :error which is very useful!

However, sometimes I want to return a more specific error from Map.fetch failure. Consider the following case:

states = %{"AL" => "Alabama", "AK" => "Alaska", "AR" => "Arkansas", ... }
Map.fetch(states, abbreviation)

This will return either {:ok, name} or :error. However, for the caller's convenience, I would return {:ok, name} or {:error, "State not found!"}.

Map.get/2 could be used:

case Map.get(states, abbreviation) do
  nil -> {:error, "State not found!"}
  name -> {:ok, name}
end

or Map.fetch/2:

case Map.fetch(states, abbreviation) do
  {:ok, name} -> {:ok, name}
  :error -> {:error, "State not found!"}
end

But I would truly like to have a Map.fetch/3 function where the third argument is alternate default value (a la Map.get/3)

Map.fetch(states, abbreviation, {:error, "State not found!"})

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

Greg Vaughn

non lue,
26 janv. 2021, 17:08:2926/01/2021
à elixir-l...@googlegroups.com
This can be accomplished by using a `with` in which the `else` clause is the good result. Readability is up for debate of course.

with :error <- Map.fetch(states, abbreviation), do: {:error, "State not found"}

-Greg Vaughn
> To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/4ff59ad2-bda9-3353-494a-9de0d1c05e78%40gmail.com.

Répondre à tous
Répondre à l'auteur
Transférer
0 nouveau message