[Proposal] Support keyword list short hand with the cons operator

71 views
Skip to first unread message

Allen Madsen

unread,
Sep 13, 2017, 8:56:28 AM9/13/17
to elixir-lang-core
Yesterday I wrote code like the following:

[x: 1, y: 2 | [z: 3]]

I was really surprised when it didn't compile:

** (CompileError) iex:1: undefined function |/2
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1355: :lists.mapfoldl/3

The non-shorthand version works fine.

[{:x, 1}, {:y, 2} | [z: 3]]
#=> [x: 1, y: 2, z: 3]

Alexei Sholik

unread,
Sep 14, 2017, 12:54:11 PM9/14/17
to elixir-lang-core
Questions like this should be asked on the Elixir Forum.

The problem with the expression `[x: 1, y: 2 | [z: 3]]` is that it is parsed as `[x: 1, y: (2 | [z: 3])]`. As you may guess, the subexpression `2 | [z: 3]` does not make sense.

There's actually a working way to build the keyword list you want: [x: 1, y: 2] ++ [z: 3].

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/6e89a635-6642-4f42-ace8-4a36119fa4e5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Allen Madsen

unread,
Sep 14, 2017, 6:18:38 PM9/14/17
to elixir-l...@googlegroups.com
Sorry, I wasn't asking a question. I was making a proposal as it says in the title. Maybe the body of my message didn't convey that well or are you saying that proposals to change the language shouldn't be made on this mailing list?

You're right that the current parsing of that statement does not make sense. I was suggesting instead of it being parsed like `[x: 1, y: (2 | [z: 3])]` it was parsed like `[{:x, 1}, {:y, 2} | [z: 3]]`.

It is definitely true you can use the list concatenation operator to do what I'm suggesting, but that can have performance implications if the list on the left is large. The cons operator on the other hand is a constant time operation.

This was something I noticed that seemed inconsistent to me. If there's a very good reason not to support it, that's fine.

Michał Muskała

unread,
Sep 15, 2017, 12:34:38 AM9/15/17
to elixir-l...@googlegroups.com
If the list on the left is constant, ++ operator will compile to exactly the same code as cons operator.

[x, y] ++ tail and [x, y | tail] compile to the same thing.

Michał.
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/CAK-y3CstkBkwACf6HVMyD0MioTjUo8vtPq_ca1KrTzhQPY4rUw%40mail.gmail.com.

José Valim

unread,
Sep 15, 2017, 2:57:20 AM9/15/17
to elixir-l...@googlegroups.com
This was something I noticed that seemed inconsistent to me. If there's a very good reason not to support it, that's fine.

The reason is that this is valid syntax on typespecs:

    [kind: :unique | :duplicate, name: atom()]
    [name: atom(), kind: :unique | :duplicate]

Generally speaking, changing operators precedence is going to backfire one way or the other. :)



José Valim
Skype: jv.ptec
Founder and Director of R&D

Allen Madsen

unread,
Sep 15, 2017, 8:03:39 AM9/15/17
to elixir-l...@googlegroups.com
Thanks for the explanation José. That makes much more sense now. I think that's a reasonable trade off.

Thanks Michal, I was unaware of that. When I wrote about it potentially having a performance impact I was thinking more about prepending the head in a reduction. But the case you mentioned definitely is the more common code.

Also, thanks Alexei, it makes more sense to me with Michal's explanation why you suggested using ++.
Reply all
Reply to author
Forward
0 new messages