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.

Reply via email to