For example, maps, sets, and vectors can each be used either as functions or as data objects (meaning they can be the first item or any other item of a form). Was this functionality provided via Clojure? If so, how an I define something that operates the same way?
In my case, as a learning exercise I want to define a “Matrix” thing that can either be viewed as a data structure itself or used as a transformation upon appropriate things.
Yes, you can hook into this yourself. Clojure can invoke anything that implements the clojure.lang.IFn interface. If you want to explicitly be able to invoke it you can implement IFn and the invoke arities that are important to you. For something like a Matrix, you probably want a deftype.
For example, if you wanted to create a Rectange type and be able to invoke it to get it’s area (this is a totally arbitrary example):
(deftype Rectangle [x y]
clojure.lang.IFn
(invoke [_] (* x y)))
(def rect (->Rectangle 4 5))
(rect) ;; 20
You can do the same thing in ClojureScript, but the syntax is a little different unfortunately. Use IFn instead of clojure.lang.IFn, and add a dash to invoke.
Thanks for the help. I have working CLJ code (still need to do the work of making it fully CLJC compatible). I found I had to implement several type functions to get it to play nice with things like my matrix multiplication function, so I needed to implement Counted and ISeq in addition to IFn. Here’s what I ended up with (and it works):
It feels like there’s probably a shorter way of subscribing to other types than line-by-line definitions of things like seq and count. Is there a simpler way?