Skip to content

ObjectAccessorMethods

Luo Tian edited this page Sep 24, 2018 · 6 revisions

As fun-map can wrap functions inside, like this:

(defn numbers-obj
  [numbers]
  (fun-map
    {:numbers numbers
     :cnt     (fnk [numbers] (count numbers))
     :sum     (fnk [numbers] (reduce + 0 numbers))
     :average (fnk [cnt sum] (float (/ sum cnt)))}))

Does it look like a constructor for a class numbers, which has property accessor like :cnt, :sum, :average? Indeed, you can access these properties as if they are stored inside.

(:average (numbers-obj [3 5 6 9])) ;=> 5.75

What if instead of functions returning plain value, we return a function?

(defn numbers-with-methods
  [numbers-obj]
  (assoc numbers-obj
    :average> (fnk [average]
               (fn [another-numbers]
                (> average (:average another-numbers))))))

(def numbers-1 (numbers-with-methods (numbers-obj [3 5 6 8 12])))
(def numbers-2 (numbers-obj [8 1 -3 18]))
((:average> numbers-1) numbers-2) ;=> true

This :average> looks just like a method of numbers-with-methods object from the perspective of OO. Of course, it is cumbersome to call a method like this. We can introduce some syntax here.

(defmacro +>
  [obj method-name & args]
  `(('~method-name ~obj) ~@args))

(+> numbers-1 :average> numbers-2) ;=> true

These numbers-obj objects are immutable data, but if we like mutable data structure like in another OO, nothing stops we do so:

(def a-numbers (atom [3 5 6 8]))
(def mutable-numbers (numbers-obj a-numbers))
(:average mutable-numbers) ;=> 5.5
(reset! a-numbers [8 15 7 22 -6])
(:average mutable-numbers) ;=> 9.2

We made no changes to the code, created a mutable numbers-obj!

Clone this wiki locally