Reputation: 10097
I want to get the "default value" of an object based on its type in clojure. For example, it might work like this:
(default-value 15) ;; => 0
(default-value "hi") ;; => ""
In both cases, it takes the type of the value, and returns a "blank" instance of that value's type. The best I can come up with is
(defn default-value [x] (.newInstance (.getClass x)))
But this doesn't work on numbers:
repl=> (.newInstance (.getClass 1))
NoSuchMethodException java.lang.Long.<init>() java.lang.Class.getConstructor0 (Class.java:3082)
Upvotes: 0
Views: 191
Reputation: 29984
Looks like multimethods could be a good fit:
(defmulti getNominalInstance (fn [obj] (.getClass obj)))
(defmethod getNominalInstance java.lang.Long [obj] (Long. 0))
(defmethod getNominalInstance java.lang.String [obj] "")
(prn :long (getNominalInstance 5))
(prn :string (getNominalInstance "hello"))
;=> :long 0
;=> :string ""
The problem is that Long only has 2 constructors, which take either a primitive long or a string, respectively.
Long(long value) - Constructs a newly allocated Long object
that represents the specified long argument.
Long(String s) - Constructs a newly allocated Long object
that represents the long value indicated by the String parameter.
It isn't legal Java to say "new Long()", which is what newInstance()
does. So, you have to do it manually with defmulti
or equivalent.
Upvotes: 4
Reputation: 92117
There's not really any such thing as a "default value" for a type, unless you are looking for the way that Java default-initializes stuff in constructors when you don't provide an explicit value. That's just:
If you want something more sophisticated (eg, string=>"") you will have to write it yourself, by dispatching somehow on the type of the object into code you control.
Upvotes: 2