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
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
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
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.
Popular in Discussions
Other popular 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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










