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
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