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

34 visualitzacions
Ves al primer missatge no llegit

Paweł Urbanek

no llegida,
26 de gen. 2021, 3:38:1326/1/21
a 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

no llegida,
26 de gen. 2021, 3:40:1326/1/21
a 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

no llegida,
26 de gen. 2021, 3:47:0026/1/21
a 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

no llegida,
26 de gen. 2021, 3:48:2326/1/21
a elixir-l...@googlegroups.com
Hello,
I think you're looking for `.get_lazy/3` functions.

Best regards,
Jean

Paweł Urbanek

no llegida,
26 de gen. 2021, 3:53:0226/1/21
a elixir-lang-core
Thanks, I was not aware of that.

Jonathan Arnett

no llegida,
26 de gen. 2021, 16:50:1526/1/21
a 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

no llegida,
26 de gen. 2021, 17:08:2926/1/21
a 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.

Respon a tots
Respon a l'autor
Reenvia
0 missatges nous