spacebat

spacebat

Kword - A library of keyword-list handling functions to complement Keyword

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)
    ...
  end

The 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])
    ...
  end

If 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.

Most Liked

sodapopcan

sodapopcan

“Considered Harmful” titles always make me think of “Considered Harmful” Essays Considered Harmful :grin:

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

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:

from q in query,
  join: u in User,
  on: u.id == q.user_id,
  join: o in Org,
  on: o.id == u.org_id
dimitarvp

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. :+1:

Secondly, the linked article does not sell the resulting library to me. Keyword.get and Map.get are 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 is nil” – 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 like take and fetch you 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 NimbleOptions is giving homework to the reader so I am going to skip it and just use the former instead.

D4no0

D4no0

As with everything else we use, it is considered harmful when it expresses the wrong intent.

I use Keyword.get/3 in situations where an option might be missing and I have a default value for it. For example:

Keyword.get(opts, :option, default_value)

Using it in cases where having that key missing is invalid logic, you are just propagating a bug further into the system. This is especially bad when you leave the default value to nil and propagate it further, hard to debug and trace down.

spacebat

spacebat

On a tangent, Perl5 has a // operator, which is like the logical or || but only treats undef as falsey. Useful for disambiguating nil/null/undefined/missing values from defined but false ones.

Where Next?

Popular in Libraries Top

pkrawat1
Hey guyz We at @aviabird are working on a payment library in elixir/phoenix. We are targeting March 2018 to add 56 Gateways to it. Have...
New
deadtrickster
I’ve just released stable versions of my Prometheus Elixir libs: Elixir client [docs]; Ecto collector [docs]; Plugs instrumenter/Export...
New
kevinlang
Hey all, We have made an Ecto3 Adapter for SQLite3, ecto_sqlite3! We have successfully on-boarded the full suite of integration tests (...
New
nikokozak
Hello all, I’ve been working on Svonix - a library for quickly integrating Svelte components into Phoenix views. It’s a much-needed succ...
New
treble37
Just looking for a little feedback on a tiny helper library I built - Sometimes I find the need to convert maps with atom keys to maps...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
wfgilman
I’ve cleaned up and open sourced three financial libraries I was using for my company. They are bindings for the APIs of these three comp...
New
gjaldon
As the title states, EctoEnum has just been updated after some time of hardly any activity in the repo. Here’s the latest release: https:...
New
Azolo
Hey everyone, I just released WebSockex which is a Elixir WebSocket client. WebSockex strives to work as a OTP special process, be RFC6...
New
Hal9000
Here is my first stab at this. README pasted below. https://github.com/Hal9000/elixir_random Comments and critiques are welcome. Th...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
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 45766 226
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

Sub Categories:

We're in Beta

About us Mission Statement