> 1. Maps are slower (significantly enough to avoid IMHO), but do give the
flexibility desired (1.79x slower, which could compound if in the wrong
place)

Do you have a source for the 1.79 slower?

I don't expect maps to be slower but, more importantly, the difference here
should be negligible because options rarely exceed more than a dozen keys
and in those scenarios lookups are in the order of single-digit
microseconds (source
<https://github.com/erlang/otp/issues/6139#issuecomment-1182995087>) *in
the worst case*. So it seems counter productive to say you wouldn't pick
the more flexible option because an operation will take 1.75us instead of
1us (assuming it is indeed slower). :)

Plus maps have other benefits such as reading multiple keys at once which
will certainly offset keyword lists.

> Keyword lists must be matched in exact order, and flexibility with them
is limited

Yes, this is a pain point I see people running into. Especially given that
you are not supposed to match on keyword lists.




On Thu, Oct 27, 2022 at 11:01 PM Brandon Gillespie <bran...@cold.org> wrote:

> The challenge I've seen, faced, and had team members face time and time
> again, is that pattern matching only goes so far. The limitations are:
>
> 1. Maps are slower (significantly enough to avoid IMHO), but do give the
> flexibility desired (1.79x slower, which could compound if in the wrong
> place)
> 2. Keyword lists must be matched in exact order, and flexibility with them
> is limited
>
> It's the frequent edge cases that end up causing problems: they end up
> being a little clunky in practical use.
>
> -Brandon
>
>
> On 10/27/22 2:30 PM, José Valim wrote:
>
> [...]
>
> And Elixir has opted into pattern matching for this particular feature set.
>
> On Thu, Oct 27, 2022 at 10:19 PM Felipe Stival <v0id...@gmail.com> wrote:
>
>> This library implements this functionality, albeit on a peculiar way:
>> https://hex.pm/packages/defnamed. It suffers from the issues explained
>> by Marc-André.
>>
>> On Thu, Oct 27, 2022, 21:05 Marc-André Lafortune <
>> marc-an...@marc-andre.ca> wrote:
>>
>>> If I understand your proposal, calling `do_a_thing(old: "older value",
>>> new: "newer value")` would need to know the signature of `do_a_thing` at
>>> *compile-time*. Among other things, two modules wouldn't be able to call
>>> each other's functions this way, as one couldn't be compiled without the
>>> other... Also there would be no way to know if `do_a_thing` uses named
>>> function arguments, so any function call using keywords would introduce a
>>> compile-time dependency.
>>>
>>> That being said, I miss Ruby's named arguments, and wish the default
>>> syntax for Elixir was building maps instead of keywords, but that can't
>>> change. Having a nice syntax for map arguments with defaults could be
>>> interesting though.
>>> On Thursday, 27 October 2022 at 09:59:48 UTC-4 Brandon Gillespie wrote:
>>>
>>>> Ordering of arguments is an age-old programming challenge (creating
>>>> many bugs). Type checking and pattern matching help, but are also limited.
>>>> We currently have two indirect ways of having named arguments, but both
>>>> have challenges:
>>>>
>>>>    1. Keyword lists — pattern matching must match the exact order of
>>>>    the listed arguments, which doesn't help the issue here which is 
>>>> ordering,
>>>>    let alone optional arguments, leading to extraneous in-function calls to
>>>>    Keyword.get.
>>>>    2. Maps — while this supports optional arguments, it has the
>>>>    overhead of creating and destructing a map for a simple function call.
>>>>    Benchmarking this vs ordered arguments shows it's 1.79x slower than 
>>>> simply
>>>>    using ordered arguments. That's an overhead that builds up on every
>>>>    function (I didn't benchmark keyword lists, sorry).
>>>>    3. Existing syntax to handle named arguments as keywords should
>>>>    still be handled, for backwards compatibility, making it harder to do 
>>>> this
>>>>    sort of thing.
>>>>
>>>> To preface the proposal, I realize this may simply not be possible with
>>>> the limitations of the parser/compiler that we have today.
>>>>
>>>> Proposal:
>>>>
>>>> Add a compile-time named/pinned argument syntax in the function
>>>> declaration head, which allows the naming of arguments as if it were a
>>>> keyword list, but instead, the keys are mapped to the variable names/pins
>>>> and, if necessary, are rearranged to keep the ordering correct.
>>>>
>>>> This will not work with conventional keyword arguments, where one
>>>> expects a keyword list—if using the named/pinned syntax, keyword arguments
>>>> may not be used. It's one or the other, not both.
>>>>
>>>> If this named syntax exists on a function head, then a calling function
>>>> may use the `name: value` syntax and it will align the values to the named
>>>> argument at compile time (no keyword lists are used at runtime).
>>>>
>>>> Example:
>>>>
>>>> Using `&` as a reference for the naming (or possibly if not that, the
>>>> asterisk):
>>>>
>>>>   def do_a_thing(&new, &old)
>>>>
>>>> Would accept any of these calls, and in all cases the variable values
>>>> within the called function would align properly:
>>>>
>>>>   do_a_thing("newer value", "older value")
>>>>   do_a_thing(new: "newer value", old: "older value")
>>>>   do_a_thing(old: "older value", new: "newer value")
>>>>
>>>> Optional named arguments in the same manner as optional arguments today:
>>>>
>>>>   def do_a_thing(&new, &old, &optional \\ "extra info")
>>>>
>>>> Optional ideas:
>>>>
>>>>
>>>>    1. If rearranging the arguments at compile time is not easily
>>>>    feasible, it could simply just raise a compiler error when out of order,
>>>>    and then strip the names when they are properly ordered.
>>>>    2. If using named/pinned arguments, always require them to be named
>>>>    (thus, the first example above would be invalid). However, this comes 
>>>> with
>>>>    its own challenge, notably what about when using pipelines? Perhaps just
>>>>    allow that.
>>>>    3. If it's too challenging to use the same syntax as keyword lists,
>>>>    another naming convention could be used. It's just ... uglier.  Perhaps 
>>>> if
>>>>    using `*` instead it would be on both sides (function head, and calling
>>>>    function), such as:
>>>>
>>>>   def do_a_thing(*new, *old)
>>>>   ...
>>>>   do_a_thing(*new: "newer value", *old: "older value")
>>>>
>>> --
>>> 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/0928ddde-8ca2-4110-a223-d62b711529a7n%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/0928ddde-8ca2-4110-a223-d62b711529a7n%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/CAKC64%2Bz6yHpK%3DJpN1fd7fgz9Z-m2UmsA0a852obGrjCpXzN1-w%40mail.gmail.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/CAKC64%2Bz6yHpK%3DJpN1fd7fgz9Z-m2UmsA0a852obGrjCpXzN1-w%40mail.gmail.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/CAGnRm4%2BsNgEUVdYQv_N6cu90O%2BzheNs1UPo5bZPw8-tT4UROhA%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BsNgEUVdYQv_N6cu90O%2BzheNs1UPo5bZPw8-tT4UROhA%40mail.gmail.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/e77b7315-625a-4c8e-0e63-bbd03116fbbe%40cold.org
> <https://groups.google.com/d/msgid/elixir-lang-core/e77b7315-625a-4c8e-0e63-bbd03116fbbe%40cold.org?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/CAGnRm4L%2BJ1zYcizc44RtK-tnX3QGSPojVhHTAXE3toWNyXbCew%40mail.gmail.com.

Reply via email to