Search code examples
clojurerecords

Uniform access to Clojure records with probabilistic fields


Is there an elegant way to create and use records with a mix of constant and probabilistic fields. I would like to be able to do something like the below, where "sampler" is a function that returns a sample from some distribution. the goal is to make it transparent to the user whether the filed accessed is constant or probabilistic.

> (defrecord Stat [val1 val2])

> (def s1 (Stat. 1 sampler))

> (:val1 s1)

> 1

> (:val2 s1)

> 4

> (:val2 s1)

> 2

Solution

  • Having keyword lookup behave in a way other than simply looking up a fixed value in a map is possible, for custom deftypes, but I strongly recommend against it. Not only is it a lot of work, it will defy the expectations of everyone reading your code.

    However, a slight adjustment to your requirements yields an easy solution: Instead of (:val1 x), write (x :val1). Now x can simply be a function, which lets the input it receives dictate its behavior:

    user> (defn stat [distributions]
            (fn [sample]
              ((get distributions sample))))
    
    #'user/stat
    user> (def s1 (stat {:val1 (constantly 1)
                         :val2 #(rand-int 5)}))
    #'user/s1
    user> (s1 :val1)
    1
    user> (s1 :val2)
    3
    user> (s1 :val2)
    4