djhaskin987
djhaskin987

Reputation: 10097

Get the "default value" of an object's type in clojure?

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

Answers (2)

Alan Thompson
Alan Thompson

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

amalloy
amalloy

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:

  • boolean=>false
  • number=>0
  • object=>null

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

Related Questions