I think that this is an interesting idea, but as Enumerable is a protocol, it is possible to implement enumerability for any given struct, as `MapSet` is enumerable.
This SO answer <https://stackoverflow.com/questions/39609255/how-can-i-check-whether-the-protocol-is-implemented#39609295> suggests using the Protocol.impl_for/1 callback instead. It can’t be used as a guard, but it gives a more accurate answer. Whether `is_real_map/1` (or a different name) is more readable than `when is_map(term) and not is_struct(term)`, I can’t say because if I need to handle structs differently, I would generally use two different function heads (`def foo(term) when is_struct(term) do term |> Map.from_struct() |> foo() end` and `def foo(term) when is_map(term) do … end`). -a On Thu, Dec 22, 2022 at 1:25 AM vtm <vtmilya...@gmail.com> wrote: > hey all, thanks for you work on such a beautiful lang. > > Small proposal. People sometimes get confused about data structures which > based on maps. > for instance: > ``` > iex(3)> {:ok, datetime} = DateTime.now("Etc/UTC") > {:ok, ~U[2022-12-22 05:53:36.228720Z]} > iex(5)> is_struct(datetime) > true > iex(6)> is_map(datetime) > true > ``` > but here i got an error > ```elixir > iex(11)> Enum.each(datetime, &Function.identity/1) > ** (Protocol.UndefinedError) protocol Enumerable not implemented for > ~U[2022-12-22 05:53:36.228720Z] of type DateTime (a struct) > ``` > > i have in a codebase in function definition something like > `where is_map(map_name) and not is_struct(map_name)` > what i suggest to do is to create a macro `is_real_map` to check only real > maps as a key-value storage with Enumerable impl > ```elixir > @doc """ > Returns true if `term` is a map and not is struct; otherwise returns > `false`. > > Allowed in guard tests. > > ## Examples > > iex> is_real_map(%{oi: :blz}) > true > > iex> is_real_map(URI.parse("/")) > false > > """ > @doc since: "1.16.0", guard: true > defmacro is_real_map(term) do > case __CALLER__.context do > nil -> > quote do > case unquote(term) do > %_{} -> false > %{} -> true > _ -> false > end > end > > :match -> > invalid_match!(:is_real_map) > > :guard -> > quote do > is_map(unquote(term)) and not :erlang.is_map_key(:__struct__, > unquote(term)) > end > end > end > ``` > > > > > -- > 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-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/1f26dae3-9c67-446b-91d0-51bf1c5f3666n%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/1f26dae3-9c67-446b-91d0-51bf1c5f3666n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- Austin Ziegler • halosta...@gmail.com • aus...@halostatue.ca http://www.halostatue.ca/ • http://twitter.com/halostatue -- 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-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAJ4ekQtcuNm-ow1UiQbMVK8m3oJ8ZMi%3DvwGRjHjFOoEgR-AY%3DA%40mail.gmail.com.