Hi all, while we are on this, I’d like to share the `mapset/1 macro we use to simplify MapSet matching
@doc """ Mapsets in matches are matched the same way as maps, that said the following would be matched ```elixir fn mapset() -> :ok end.(MapSet.new()) fn mapset() -> :ok end.(MapSet.new([1, 2])) fn mapset([1]) -> :ok end.(MapSet.new([1, 2])) ``` and the following would not ```elixir fn mapset([1]) -> :ok end.(MapSet.new()) fn mapset([2]) -> :ok end.(MapSet.new([1])) ``` """ @doc guard: false @spec mapset(list()) :: Macro.t() defmacro mapset(list) do case __CALLER__.context do :guard -> raise_opts = fn description -> [ file: Path.relative_to_cwd(__CALLER__.file), line: __CALLER__.line, description: description ] end raise CompileError, raise_opts.("`mapset/1` macro cannot be used in guards") :match -> list_ast = Enum.map(list, fn {:^, meta, [{_, _, _} = elem]} -> {{:^, meta, [elem]}, []} # to raise properly, we need the following line {_var_name, meta, _} = var -> {{:var!, meta, [var]}, []} elem -> {elem, []} end) map_ast = {:%{}, Macro.Env.location(__CALLER__), list_ast} quote do: %MapSet{map: unquote(map_ast)} nil -> quote do: MapSet.new(unquote(list)) end end It could be a great addition to the guard, specifically in tests. On Sun, Mar 3, 2024 at 2:37 PM Bruce Tate <br...@grox.io> wrote: > I'm excited for this one, Chris. Thanks for taking it on. > > -bt > > On Sat, Mar 2, 2024 at 5:28 PM Christopher Keele <christheke...@gmail.com> > wrote: > >> >> PR opened here <https://github.com/elixir-lang/elixir/pull/13386>! >> On Saturday, March 2, 2024 at 2:21:29 AM UTC-6 José Valim wrote: >> >>> Please do submit a PR for MapSet.is_member. Since then, we have added >>> map related guards to Kernel, which also do duplicate existing functions in >>> Map, So I think some of my original concerns are no longer relevant. There >>> is also no need to deprecate any of the existing functions. >>> >>> On Sat, Mar 2, 2024 at 00:30 Christopher Keele <christ...@gmail.com> >>> wrote: >>> >>>> MapSets are *very* useful constant time data structures; and I keep on >>>> finding myself wishing there was a future-proof approved way to use them in >>>> guards. Consider this my +1. >>>> >>>> I believe eksperimental's original rationale still holds: >>>> >>>> 1. :erlang.is_map_key/2, as well as :erlang.map_get/2, are awkward to >>>> use guards (as of writing, by design, to encourage destructuring) >>>> 2. a MapSet's .map is a private field and should not be >>>> accessed/destructured directly (see: various pain points when the internal >>>> implementation of Range fields changed) >>>> >>>> I'd like to re-open a proposal for a guard-safe MapSet.is_member/2, >>>> with the implementation: >>>> >>>> defmodule MapSet do >>>> defguard is_member(map_set, value) >>>> when is_struct(map_set, __MODULE__) and >>>> :erlang.is_map_key(value, map_set.map) >>>> end >>>> >>>> This would bring the core conceit of MapSets (constant-time set >>>> membership) into where they are very valuable (constant-time guard >>>> operations for pattern matching against function heads). >>>> >>>> I am not convinced that deprecating MapSet.member?/2 adds much value if >>>> it would force developers to require MapSet before using its core >>>> functionality, so I'm content having a bit of duplication. Similarly, >>>> checking the size of a MapSet is less core to its utility, and again I >>>> wouldn't want to developers to have to require the module just to check the >>>> size—so I'm proposing that addition. Just the single guard! >>>> On Thursday, December 24, 2020 at 1:37:40 AM UTC-6 José Valim wrote: >>>> >>>>> Because if I have a MapSet, I would prefer to call MapSet API to make >>>>> the intent clearer. >>>>> >>>>> On Thu, Dec 24, 2020 at 4:48 AM eksperimental <eksper...@autistici.org> >>>>> wrote: >>>>> >>>>>> On Mon, 21 Dec 2020 22:37:53 -0500 >>>>>> eksperimental <eksper...@autistici.org> wrote: >>>>>> >>>>>> > Hi list, >>>>>> > I would like to propose to convert two existing functions to guards >>>>>> in >>>>>> > the MapSet module. >>>>>> > >>>>>> > 1. Is MapSet.size/1. I found myself not being able to use this >>>>>> > function in guards, and having to port my code, unless I want to get >>>>>> > into the bad habit of reading the internal structure of the struct >>>>>> > which is an opaque type. >>>>>> > This guard can be implemented with :erlang.map_get/2 >>>>>> > >>>>>> > 2. Deprecate MapSet.member?/2 in favor of MapSet.is_member/2 >>>>>> > >>>>>> > Thank you for reading >>>>>> > >>>>>> >>>>>> Actually, why are we having MapSet.member?/2 when we have >>>>>> Enum.member?/2. It is redudant. >>>>> >>>>> >>>>>> >>>>>> -- >>>>>> 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/5fe40f76.1c69fb81.f8161.5ba3SMTPIN_ADDED_MISSING%40gmr-mx.google.com >>>>>> . >>>>>> >>>>> -- >>>> 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/93cec4b9-526c-48a9-9bb6-94c06c74827bn%40googlegroups.com >>>> <https://groups.google.com/d/msgid/elixir-lang-core/93cec4b9-526c-48a9-9bb6-94c06c74827bn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >> 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/75e42f08-582c-40ad-97cb-6ee9d030626cn%40googlegroups.com >> <https://groups.google.com/d/msgid/elixir-lang-core/75e42f08-582c-40ad-97cb-6ee9d030626cn%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > > > -- > > Regards, > Bruce Tate > CEO > > > <https://bowtie.mailbutler.io/tracking/hit/f8218219-d2a8-4de4-9fef-1cdde6e723f6/c7c97460-016e-45fb-a4ab-0a70318c7b97> > > Groxio, LLC. > 512.799.9366 > br...@grox.io > grox.io > > -- > 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/CAFXvW-7ErbSzOK7-xCQrwn%3DL3Sru7YyE5SnVdOp6MS6RdLf0Zw%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-7ErbSzOK7-xCQrwn%3DL3Sru7YyE5SnVdOp6MS6RdLf0Zw%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- AM -- 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/CAGF5_6cbsGNMJbbfYOVYysC8t-nLJf9F05dAY3sqaXB0kkRbpw%40mail.gmail.com.