Reputation: 9176
It is idiomatic in lisps such as Clojure to use simple data-structures and lots of functions. Still, there are many times when we must work with complex data-structures composed of many simpler ones.
My question is about a matter of good style/practice. In general, should we create functions that take the entire complex object, and within that extract what we need, or should they take exactly and only what they need?
For concreteness, I compare these two options in the following psuedo code
(defrecord Thing
[a b])
(defn one-option
[a]
.. a .. ))
(one-option (:a a-thing))
;; ==============
(defn another-option
[a-thing]
.. (:a a-thing) .. ))
The pros of one-option-f
is that the function is simpler, and has fewer responsibilities. It is also more compositional - it can be used in more places.
The downside is that we may end up repeating ourselves. If, for example, we have many functions which transform one Thing
into another Thing
, many of which need use one-option
, within each one we will find ourselves repeating the extraction code. Of course, another option is to create both, but this also adds a certain code overhead.
Upvotes: 3
Views: 141
Reputation: 4643
Do both. To begin with, provide functions that transform the simplest structures, then add convenience functions for handling more complex structures which compose the functions that handle the simple ones.
Upvotes: 0
Reputation: 13483
I think the answer is "It depends" and "It doesn't matter as much in Clojure as it does in object systems". Clojure has a number of largely orthogonal mechanisms designed to express modes of composition. The granularity of function arguments will tend to fall out of how the structure of the program is conceived of in the large.
So much for the hot air. There are some specifics that can affect argument granularity:
get-in
and assoc-in
, for examples).Upvotes: 1