devboy
devboy

Reputation: 262

Extending the constructor of a deftype in clojurescript

When creating a type via deftype in clojurescript:

(deftype SomeObject [a b c]
    Object
        (update [_]
            (set! (.-a _) 5)
            (set! (.-b _) 6) ))

Is there a possibility to extend the constructor? I would like to do some initialization of my object when it's being created!

Upvotes: 4

Views: 1020

Answers (3)

devboy
devboy

Reputation: 262

Thanks guys, I will go with factory methods then. Probably makes the most sense in ClojureScript anyway! Think I'll try to avoid deftypes/Types in the future, so a factory method can hide that pretty well. Still in the transitioning phase to functional programming ;)

Upvotes: 0

Michał Marczyk
Michał Marczyk

Reputation: 84331

There is no support for that in deftype, no; the Clojure(Script) equivalent is to define a factory function, perhaps make-some-object, and use that instead of the actual constructor. See amalloy's answer for an example and rationale.

Of course in JavaScript, constructors are simply functions and you can certainly use ClojureScript to define a function which will work as a JS constructor would:

;; "constructor" with default field values
(defn Point [x y]
  (this-as this
    (set! (.-x this) (if x x 10)) ; NB. Clojure truth semantics are used
    (set! (.-y this) (if y y 20))))

(.-x (Point. 2))
;= 2
(.-y (Point. 2))
;= 20

That goes against the overall spirit of the language a bit, and so is not advisable except in special circumstances. (Interop with a JS API expecting a constructor as an argument perhaps?)

Upvotes: 4

amalloy
amalloy

Reputation: 91857

The constructor for a deftype is intentionally minimalistic: it just copies N objects to hold your data fields. There's no need to make it more powerful, because you already have a tool to do the job: plain old functions are all you need.

(defn foo [opts]
  (if-not (acceptable? opts) 
    (throw (Exception. "No way, man"))
    (Foo. (:x opts) (:y opts)))

is a simple example of wrapping a deftype constructor. Even if deftype allowed you to imbue a "real" constructor with this sort of logic, it's nice to create an abstraction barrier between the client API and the underlying representation, so that client code can be mainly unaffected if the representation changes.

Upvotes: 3

Related Questions