Suppose I want to define two mutually recursive functions within a local scope. I can do this with letfn:
(letfn
[(f [x] (if (= x 0) (g x) true))
(g [x] (if (= x 1) (f x) false))]
(f 0))
But letfn is quite restricted, compared to let, as it accepts only "function specs," not arbitrary expressions. My question is: what if I want to attach metadata (using with-meta) to both f and g, so that within f, I can read g's metadata, and within g, I can read f's metadata? Is this possible in Clojure?
(For context, I am trying to implement a fn-like macro that automatically attaches certain metadata to the function being created. I'd like these auto-annotated fns to be instantiable wherever a normal Clojure function is, including inside a letfn. But I don't see how I can define a letfn-like macro that attaches the metadata, because it would ultimately have to desugar to letfn, which cannot attach metadata.)
Don't forget about with-local-vars:
(with-local-vars [f (fn [x] (if (= x 0) (g x) true))
g (fn [x] (if (= x 1) (f x) false))]
(reset-meta! f {:f 3})
(reset-meta! g {:g 2})
with results:
(f 0) => false
(f 1) => true
f => #<Var: --unnamed-->
(var-get f) => #object[tst.demo.core$fn__20698$fn__20699 0x1eb2d718 "tst.demo.core$fn__20698$fn__20699@1eb2d718"]
(meta f) => {:f 3}
(meta g) => {:g 2}
You can also use var-get and var-set to access/change the value of the local vars.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With