derek-zhou

derek-zhou

How to design function that take both another funtion and a keyword as parameters

If a function takes a keyword as one of its parameters, we normally put it last:

def my_func(a, b, attrs \\ []) do
...
end

So at call site we can write: my_fun(1, 2, option: true)

Similarly, if a function takes another function as one of its parameters, we normally put it last:

def my_fun(a, b, func) do
    func.(a, b)
end

So at the call site, we can write nicely as:

my_fun(1, 2, fn a, b ->
    a + b
end)

Now, what if my function take both a keyword and a function as parameters?

function last

def my_fun(arg, keyword, func) do
...
end

...
my_fun(1, [
    option1: true,
    option2: false
], fn arg ->
    arg + 1
end)

Or:

keyword last

def my_fun(arg, func, keyword \\ []) do
...
end

...
my_fun(1,  fn arg ->
    arg + 1
end,
    option1: true,
    option2: false
)

The problem of function last is that keyword cannot be optional and I have to write [] around it. The problem of keyword last is that function is usually longer than the keyword, so it feels top heavy.

I played around a bit, and it seems like I can do:

high order function

defp private_fun(arg, func, keyword) do
...
end

def my_fun(arg, keyword \\ []) do
    &private_fun(arg, &1, keyword)
end

So, at the call site I can do:

my_fun(1,
    option1: true,
    option2: false
).(fn arg ->
    arg + 1
end)

My question is, does it look weird? Because I’ve not seen other people do this.

Most Liked

dimitarvp

dimitarvp

Well Task.async_stream has no problem with having a function parameter and then keyword list as a last parameter, by the way.

I personally would just put the function inside the keyword list, which gives us the nice advantage of explaining what is the goal of the function.

And then you can do stuff like:

do_stuff(
  username,
  password,
  token_expiration_policy: :hourly,
  callback: fn token -> refresh_token(token) end
)
derek-zhou

derek-zhou

So you prefer to put the function as the last in the keyword list. It looks nice on the call site, not so on the definition site. In my case the function is mandatory, so the keyword list become mandatory too. Also, I’d have to write the code to handle the case when the caller forgot to add the callback function.

dimitarvp

dimitarvp

I agree it’s tedious to code. I used NimbleOptions with some success but was left unsatisfied. The best dev UX that I have achieved for myself was basically a macro to raise an error if a minimum set of keys weren’t present – right at the start of the function – and then operate more or less as usual after.

But even that still doesn’t rid you of having to validate the values passed in the keyword list.

In short, I don’t like keyword lists very much for the exact reasons you listed when saying that my idea makes for suckier coding of the definition.

Where Next?

Popular in Discussions Top

WildYorkies
It seems that the more I read, the more I find Elixir users speaking about all the ways that Elixir is not good for x, y, and z use cases...
New
thojanssens1
It would be nice to be able to define a redirect from one route to another from the router.ex file. E.g.: redirect "/", UserController, ...
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
ricklove
I was just introduced to Elixir and Phoenix. I was told about the 2 million websocket test that was done 2 years ago. From my research, t...
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
tmbb
This is a post to discuss the new Phoenix LiveView functionality. From Chris’s talk, it appears that they generate all HTML on the serve...
342 18243 126
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
New
sergio
There’s a new TIOBE index report that came out that shows Elixir is still not in the top 50 used languages. It also goes on to call Elix...
New
AstonJ
It’s been a while since we’ve had a thread like this, so what better way to kick off the year with :003: What does being an Elixir user ...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43487 311
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
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
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
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
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
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement