spacebat
A recent Reddit post Keyword.get Considered Harmful nudged me to tidy up and publish a small utility library that I’ve been using to deal with keyword lists in an ergonomic way.
Elixir keyword lists as a common representation of optional arguments to functions feels a bit clunky. You may find yourself writing something like:
def update_user_details(opts \\ []) do opts = Keyword.validate!(opts, [:name, :email, role: :guest, gender: :unspecified]) name = Keyword.fetch!(opts, :name) email = Keyword.fetch!(opts, :email) ... endThe intent of Kword is to enable list matching (there’s an order of parameters in the second argument) and to write instead:
def update_user_details(opts \\ []) do [name, email | _rest] = Kword.extract!(opts, [:name, :email, role: :guest, gender: :unspecified]) ... endIf you want to ensure required parameters are in fact supplied, use extract or extract!.
If you don’t want to allow parameters that aren’t specified, use extract_exhaustive or extract_exhaustive!.
And if you just want to pluck values out of a keyword list in the order specified, use extract_permissive which will default parameters to nil that have no default specified.
Perhaps I’ve missed something and this library isn’t actually useful, or there may be some improvement that would make it more worthwhile.
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
katafrakt
I also read that post and liked it very much, however I think it missed one opportunity to make the code better with
Keyword.validate!:By simply converting validated keyword list to a map you can use established Elixir idioms to check for required things, either by using
opts.emailnotation, or by pattern matching. But maybe I’m missing something tooD4no0
It highly depends on what kind of options you accept and how you treat them. The key concept when using keyword list vs map is that you can have duplicated keys in case of the list, then decide whether the new option overrides/appends to the old one.
sodapopcan
“Considered Harmful” titles always make me think of “Considered Harmful” Essays Considered Harmful
I’m in favour of validating keyword args and do it myself (personally I use
NimbleOptions) but that article hardcore handwaves through the entire premise of how they got there: how on earth did their tests not catch a mis-spelled option?? It sounds like they were passing the option but not actually asserting on its effects. Am I wrong or is there an obvious valid hiccup you can have here?sodapopcan
While it’s getting outside the realm of options, keywords also allow us to have order matter in the rarer situations where that’s useful:
katafrakt
Fair point, but with using
Keyword.getorKeyword.popyou don’t really decide, just take the first value. Most of the usage of keyword lists outside of Ecto I see is a workaround for Elixir not having named arguments, so converting to map makes sense. However you’re right that to keepKeyword.gets behaviour in place you actually needEnum.reverse() |> Map.new().Well, but we are in the realm of options.
dimitarvp
I support everything that helps people make less mistakes and dynamic languages like Elixir don’t provide as much protection there.
So firstly, good job.
Secondly, the linked article does not sell the resulting library to me.
Keyword.getandMap.getare something that many Elixir devs, myself included, consider an anti-pattern simply because they don’t discern between “I don’t have the key” and “I have the key but the value isnil” – in some situations this difference is meaningless but I’d bravely claim that in at least 80%, if not 90%, of the Elixir code I had to author or maintain that difference was in fact important but people ignored it and introduced bugs. So just by using functions liketakeandfetchyou can replace most of the conveniences of this library – though granted, it would take more boilerplate so the library still looks compelling.Thirdly, not comparing the new library with
NimbleOptionsis giving homework to the reader so I am going to skip it and just use the former instead.sodapopcan
The discussion is turning into a more general “why keyword lists over maps or bringing in keyword args,” so not quite, no.
spacebat
Converting to Map was my first impulse, and I guess I should benchmark it but seems a bit heavyweight compared to constructing a list. Also there is the gotcha of
Map.newtaking the last one if a key occurs more than once.spacebat
I have seen
NimbleOptionsbut bounced off when I saw how verbose it was, defining a schema with types. Looking closer now I do think there would be times I’d want exactly that.The aim of
Kwordis to provide a few relatively fast functions that I found myself wishing were in theKeywordmodule.sodapopcan
Oh ya, I got that! I wasn’t speaking against the utility of your library, just criticizing the article you linked.