add Keyword.take!/2, Map.take!/2

139 weergaven
Naar het eerste ongelezen bericht

DaTrader

ongelezen,
18 dec 2023, 05:56:1118-12-2023
aan elixir-lang-core
Many times I need to merge a subset of a keyword list or a map into another keyword list or map while requiring it to fail if not all keys are present.

For this purpose I have small utility modules called KwUtils and MapUtils where I have functions like the one below:

```
  @doc """
  Takes specified key-value pairs from the keyword list but raises if any not found.
  """
  @spec take!( keyword(), [ atom()]) :: keyword()
  def take!( kw, keys) do
    taken = Keyword.take( kw, keys)

    if length( taken) != length( keys) do
      raise "Expected all keys in #{ inspect( keys)} to be present in #{ inspect( kw)}"
    end

    taken
  end
```

It'd be nice if a corresponding function was part of the `Keyword` and `Map` modules each.

Rogério Santos

ongelezen,
27 dec 2023, 21:21:5027-12-2023
aan elixir-lang-core
I don't see such special use cases as good candidates to be included in builtins libraries.

DaTrader

ongelezen,
28 dec 2023, 04:40:0728-12-2023
aan elixir-lang-core
It's not special at all. Actually it is as generic as the current `Keyword.take/2`. You either want the operation to succeed if there aren't all keys present or you want it to fail. Those are two equally important use cases.

Artur Plysiuk

ongelezen,
21 feb 2024, 04:59:5221 feb
aan elixir-lang-core
I just came here to add the same proposal.

четвер, 28 грудня 2023 р. о 11:40:07 UTC+2 DaTrader пише:

José Valim

ongelezen,
21 feb 2024, 06:21:5621 feb
aan elixir-l...@googlegroups.com
+1 for the proposal, but it has to be implemented more efficiently than what was described here and we also need to add drop!. PRs welcome.

--
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/787ccf87-a103-4271-9d77-2101f1e23247n%40googlegroups.com.

DaTrader

ongelezen,
21 feb 2024, 06:25:3621 feb
aan elixir-lang-core
@josevalim Can you provide a hint on how to do it more efficiently other than comparing the two lengths - just an idea or where to look to?

sabi...@gmail.com

ongelezen,
21 feb 2024, 06:30:2521 feb
aan elixir-lang-core
For the record this proposal has been rejected once in the past https://groups.google.com/g/elixir-lang-core/c/cmirsH_OHKo/m/j2Um5uy-BgAJ

Damir Petkovic

ongelezen,
21 feb 2024, 06:37:2021 feb
aan elixir-l...@googlegroups.com
Thanks for sharing but I can't find where exactly it said it was rejected. Seems as if an incomplete discussion without a conclusion or am I missing something?

You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/7jRfrcPBK_w/unsubscribe.
To unsubscribe from this group and all its topics, 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/f09ac2cf-b38d-4035-871e-372d19c742c3n%40googlegroups.com.

José Valim

ongelezen,
21 feb 2024, 06:42:0521 feb
aan elixir-l...@googlegroups.com
The previous discussion said:

> Now I am thinking it may be better to not add `Map.take!/2`. It is not complicated to implement it yourself and given the possible confusion with pattern matching and that it may require both drop! and delete!, it is probably not worth it. So for now I would like to postpone adding this functionality. Sorry.

Sabiwara, since you proposed the previous time, what are your thoughts 3 years later?

sabi...@gmail.com

ongelezen,
21 feb 2024, 07:45:2721 feb
aan elixir-lang-core
I’ve been thinking about this one for a while and I’m still a bit hesitant.

Most of the time I wish for this I’m actually dealing with static keys, and despite being non-optimal the take syntax is much more compact than the pattern-matching version and has much less repetition:

Enum.map(rows, &Map.take!(&1, [:my_long_field, :another_long_field]))

vs:

Enum.map(rows, fn %{my_long_field: my_long_field, another_long_field: another_long_field} ->
  %{my_long_field: my_long_field, another_long_field: another_long_field}
end)


In the absence of Map.take!/2, I sometimes still default to Map.take/2 just for the readability even if I’d like to fail on missing keys. So Map.take!/2 would be an improvement to at least avoid silent failures.

A map_take!/2 macro could generate optimal code for static keys and keep the conciseness (best of both worlds), but I don’t think there’s a place where it fits well (the Map module has no macros, and it would be weird in Kernel perhaps?).

Another way here could be the field punning feature which is frequently discussed (example: https://groups.google.com/g/elixir-lang-core/c/P6VprVlRd6k/m/q4Jaq49eAgAJ).

Enum.map(rows, fn %{my_long_field, another_long_field} ->
  %{my_long_field, another_long_field}
end)


TLDR to answer your question Jose: yes I still think Map/Keyword take!/drop! would be useful additions, since the shortcomings also apply to Map.take/2.
But I suspect many actual usages could have a better solution.
Allen beantwoorden
Auteur beantwoorden
Doorsturen
0 nieuwe berichten