We usually use builder pattern in java, like this:
UserBuilder userBuilder = new UserBuilder();
User John = userBuiler.setName("John")
.setPassword("1234")
.isVip(true)
.visableByPublic(false)
.build();
Some of the attributes have default value, and some haven't.
Passing attributes in a map may be a solution, but it makes the argument really longer:
(def john (make-user {:name "John" :pass "1234" :vip true :visible false}))
So, my question is, is there a elegant way to achieve this?
If you want to construct some clojure structure, you can use destructuring pattern in function arguments. You will then achieve the similar thing you have already wrote.
(defn make-user [& {:keys [name pass vip visible]}]
; Here name, pass, vip and visible are regular variables
; Do what you want with them
)
(def user (make-user :name "Name" :pass "Pass" :vip false :visible true))
I doubt that you can do something in less code than this.
If you want to construct Java object (using its setters), you can use the approach Nicolas suggested.
I would normally pass attributes in via a map - there's no real issue with doing this since the attribute map is really just one argument to the make-user function. You can also do nice stuff inside make-user like merge in default attributes.
If you really want to construct such a map with a builder pattern, you can do it with a threading macro as follows:
(def john
(-> {}
(assoc :name "John")
(assoc :pass "1234")
(assoc :vip true)
(assoc :visible false)
make-user))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With