PragTob

PragTob

Passing in options: Maps vs. Keyword lists

Hey everyone, this has been on my mind for some time and I’d love your input on it!

TLDR: I feel like maps are superioer for storing and working with configuration options as compared to keyword lists and am wondering what I might be missing :slight_smile:

So, in Elixir it seems like Keyword lists are the de facto standard for passing options around. It’s what Mix.Config does and sort of advocates, to my understanding. Also it is advocated in the guides

These characteristics are what prompted keyword lists to be the default mechanism for passing options to functions in Elixir

The special characteristics mentioned are:

  • Keys must be atoms
  • Keys are ordered, as specified by the developer.
  • Keys can be given more than once

While I agree that the first one is cool/important for options, I don’t see the value of the other two for options as I see them. Given options there is only ever one option and there should be one key/value pair for it (e.g. should this print a warning? How long should this run?) and I don’t care about the ordering of the keys as I just want to get my specific value.

I can clearly see the value of these properties (and therefore Keyword lists) for DSLs like Ecto (as mentioned in the docs as well) but not for options.

In practice I found keyword lists awkward to deal with when used as options. My two main pain points are:

  • keys might occur twice while I want exactly one (when I override the value of that one key I probably want it)
  • pattern matching is hard (you gotta match on the length of the list and the order of keys) - while I love to pattern match on configuration options

To elaborate on the last point, I found it to be quite nice to pattern match on configuration options to handle them which reads very nice imo:

  defp print_configuration_information(_, %{print: %{configuration: false}}) do
    nil
  end
  defp print_configuration_information(jobs, config) do
    # do printing magic
  end

This is also why I use maps for configuration in benchee.

So in short, I feel like maps are superior for storing and working with configuration options but at the same time I somehow feel like I’m not writing idiomatic elixir and that I’m missing some great advantage of keyword lists.

Opinions/Advice/Insights? :slight_smile:

Thanks!
Tobi

Marked As Solved

josevalim

josevalim

Creator of Elixir

There are situations where the latter two properties are very handy. Ecto’s query syntax and Elixir’s OptionParser are situations where you need both. The import special form also leverages the last property (keys can be given more than once). I am pretty sure there are more examples but those are three from the top of my mind.

One of the reasons I also like to use keywords list for options is because we have a well defined dichotomy where keyword lists are used for incomplete sets (you do not need to pass all keys) while maps expect all keys to be there. This allows me to use the assertive map.key syntax when using maps. It doesn’t need to be an OR choice though. I agree pattern matching on maps is really handy and for such cases I would likely accept a keyword list but convert it to a map with defaults:

map = Enum.into(user_options, %{key: "default", other_key: false, ...})

This way the API is consistent with Elixir and you can still leverage the map properties when you don’t care about duplicates nor ordering.

25
Post #3

Also Liked

BartOtten

BartOtten

The Erlang Team has changed the default in favor of maps. Not sure if Elixir will follow.

10
Post #7
dsissitka

dsissitka

Have you seen how, for example, System.cmd/3 does it?

https://github.com/elixir-lang/elixir/blob/87710cd49521fc396f3f04fa8615f05e7f57ecc0/lib/elixir/lib/system.ex#L578-L603

BartOtten

BartOtten

In his talk at the virtual DevsForUkraine conference, José Valim addressed the question.

TLDL; he still favors lists

But when we want him to reconsider, all we need to say is: José, I think there is a performance issue with using lists for config. He will then benchmark it extensively, re-read every line involved, find 4 unrelated bugs, write fixes, push them to master and finally answer. All within 15 minutes.

Where Next?

Popular in Discussions Top

jswny
I would like to better understand what the advantages/disadvantages of umbrella applications are compared to structuring your app as as s...
New
sashaafm
I’m trying to evaluate the best combo/stack for a BEAM Web app. Right now I’m exploring Yaws a bit, after having dealt with Phoenix for a...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
laiboonh
Hi all, I am trying to convince my team to use liveview over the current react. What are some of the points where one should consider us...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
Ankhers
Just a little information upfront. Generally speaking, if I feel like I need to either break a pipe chain or use an anonymous function in...
New
Crowdhailer
I’ve been hearing much about the new formatter and it’s something I have been keen to try. I find examples buy far the most illuminating...
248 19327 150
New
mbenatti
Following https://github.com/tbrand/which_is_the_fastest |> https://raw.githubusercontent.com/tbrand/which_is_the_fastest/master/imgs...
New
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

Other popular topics Top

axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31013 112
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43757 214
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

We're in Beta

About us Mission Statement