wmnnd

wmnnd

A little while ago, I suggested to add Ecto.Changeset.optimistic_lock/4 in addition to the already existing Ecto.Changeset.optimistic_lock/3. While José didn’t like the idea, he also pointed out that if he were to consider it, he’d prefer modifying the API so that it would accept an opts Keyword list instead of adding optimistic_lock/4.

Ever since that, I have been wondering: When is it preferable to use an opts Keyword list instead of additional function parameters? What criteria do you usually use to decide which one to pick?
In many cases so far, I have found Keyword lists to be less convenient than »regular« parameters since you can’t do pattern matching on them.

My impression is that they might be better for public-facing interfaces in order to have a cleaner API. I’d then extract the values in the public function and work with them in additional private functions where pattern matching can be used again. What are your thoughts on this? Any rules of thumb that you employ when making the decision?

Showing Posts 1 to 4

Qqwy

Qqwy

TypeCheck Core Team

Keywords are useful if:

  • A function has many parameters, and remembering the order of these is hard. Using a keyword list is nice in this case, since it shows at a function call location what information is used for which purpose inside the function.
  • A function has many optional parameters.
  • A function takes some arguments from the list of options, and passes the rest on. (Note that while this is nice in some cases, it is often a bad idea as it does not ‘fail fast’; you won’t notice right away if you made a typo in the option name, for instance)

An important drawback of keyword lists is that when you ‘just’ use them, your function might be passed without some argument that it needs, so depending on where your function is used, you might want to add some descriptive error messages if people forget to pass it.

As you indeed already mentioned, not being able to pattern-match on them, as the keywords might be passed in any order is another drawback. Therefore, while they are nice in an outward-facing API, internally you’ll probably end up calling a high-arity function anyway.

So, my rule of thumb: Use them when it makes the public-facing code more clear, and use them when there are many optional arguments.

michalmuskala

michalmuskala

In general I would say that, for public functions, whenever you get more than 3 or 4 arguments you should really look into making them all (or at least some of them) a keyword. As @Qqwy mentioned many positional arguments are error prone.

Another, not mentioned yet, but very important use case are boolean arguments. Positional boolean arguments are a horrible API (most of the time), using keywords makes it slightly better since you’re able to name the thing.

Pattern matching on keywords is indeed problematic, but there are ways they can be used cleanly. A solution that I really like and often see in Erlang code, but rarely in Elixir, is reducing over the keyword to build some sanitised state.

Qqwy

Qqwy

TypeCheck Core Team

This sounds very interesting. How would this look, exactly? Would it implement reduction using primitive recursion (every time building up a one-higher arity function from the matched keyword), or in some way use e.g. Enum.reduce?

One other possibility would be to convert the keyword list to a map before pattern matching. Of course, one has to make a choice about how to handle duplicate arguments when doing that (first wins, last wins, accumulate in a list).

michalmuskala

michalmuskala

You can see an Erlang example in how poolboy process builds its state:

https://github.com/devinus/poolboy/blob/master/src/poolboy.erl#L125-L146

I can’t think of elixir examples right now.


UPDATE: You can see an elixir example in this refactoring of credo (that didn’t actually make it, but shows the idea quite nicely):
https://github.com/rrrene/credo/pull/107/files#diff-6a5ceb395f2a140c73ab593bf06fcb55

https://github.com/michalmuskala/credo/blob/b0811c97f5a509593755f6c7b7c44d6f8d18b3ff/lib/credo/cli.ex#L122-L143

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews