Open
Description
I would like to propose the following guideline:
Prefer keyword arguments on multi arity when a function allows 2 or more optional parameters to avoid passing nil on function call.
;; good
(defn my-fun [required & {:keys [optional1 optional2]}] ...)
(my-fun "required" :optional1 "o1")
(my-fun "required" :optional2 "o2")
(my-fun "required" :optional1 "o1 ":optional2 "o2")
;; bad
(defn my-fun
([required] (my-fun required nil nil))
([required optional1] (my-fun required optional1 nil))
([required optional1 optional2] (......)))
(my-fun "required")
(my-fun "required" "opt1")
; nil?
(my-fun "required" nil "opt2")
Metadata
Metadata
Assignees
Labels
No labels
Activity
bbatsov commentedon Apr 30, 2019
I don't know. I usually go with multi-arity when the params for a function are stable. Here's some thoughts that resonate with my perspective https://stuartsierra.com/2015/06/01/clojure-donts-optional-arguments-with-varargs
Any thoughts from someone else?
erez-rabih commentedon Apr 30, 2019
I think the difficult thing about more than one optional is that it might make you pass nil values to the function when calling it:
As I see it, function calls with nils in the arguments are less readable and clear. Compare that to:
Which doesn't leave you thinking "what are all these nils about"?
elzibubble commentedon May 31, 2019
FWIW... I agree with erez-rabih that when there are multiple optional and independent arguments, keyword args should be preferred. However, multi-arity should be preferred when each additional optional arg requires the preceding one to be present.
As a trivial example, imagine a
dimension
function that takes length; width and length; or height, width and length. It doesn't make sense to provide only height, so multi-arity is the correct choice here. Whereas it'd be nice ifex-info
took keyword arguments, so you could choose which ofmsg
,map
andcause
to provide.You can equally say it's more readable to use keyword arguments, or too verbose. This is up to taste and the situation imo.
A function which takes keyword arguments is more open to extension, whereas a multi-arity function is more prescriptive about what it accepts. Again, both situationally advantageous.
jgomo3 commentedon May 31, 2019
I think this is relevant: https://clojure.org/guides/destructuring#_keyword_arguments
Also this quote from there:
So, the form:
Is also valid.
Another thing to mention. In all cases, it is possible to set default values. In multi-arity asigning the default value instead of
nil
on the call to the more-arity version in the less-arity function body. In the keyword way, using the:or
option while destructuring.