Dear all, is it possible to get body of a function as string, then I'd like to print the function body. Thanks.
What's your use case? Functions in code you've written, or otherwise?
source
?
source
will do that if the body of the function is stored in a file, and its definition was loaded from the file.
Clojure does not otherwise save the body of functions as anything other than their compiled byte-code format.
one could modify Clojure to save functions in other forms than that, but it does not do so as implemented today.
@gary001 quick & dirty
(defn f [x] (into (if (instance? clojure.lang.MapEntry (first x)) {} []) x))
(f (lazy-seq {:a 1 :b 2 :c 3}))
(f (lazy-seq [1 2 3]))
(f (lazy-seq '(1 2 3)))
(f (lazy-seq `(1 2 3)))
(f (lazy-seq nil))
@ivana (f (lazy-seq (mapcat seq [{:a 1} {:b 2} {:c 3}])))
? π
@jason358 yep, seq of map entries should be a map )
even if (f (lazy-seq (mapcat seq [{:a 1} {:a 2} {:a 3}])))
π
moreover, if (*f* (*lazy-seq* (*concat* (*seq* {:a 1 :stuck_out_tongue: 2 :c 3}) [[:d 4]])))
π
but for last case one can use
(defn f [x] (into (if (every? #(instance? clojure.lang.MapEntry %) x) {} []) x))
user=> (lazy-seq (mapcat seq [{:a 1} {:a 2} {:a 3}]))
([:a 1] [:a 2] [:a 3])
user=> (f (lazy-seq (mapcat seq [{:a 1} {:a 2} {:a 3}])))
{:a 3}
(set [1 1 1 1 1 1])
#{1}
sure. i'm just pointing out perhaps a pitfall of the above function. a sequence of maps is a valid datastructure. combining them into a single map has the potential for data loss. in the domain perhaps this is acceptable, or perhaps the input data has more constraints than we know and this will never happen. but just pointing out a potential pitfall in the function
yep, reducing api to lazy seqs already reduces our possibilities. so we should accetpt it or change api. but in current state it is all we can do/ and I never met seq of map entries with duplicate keys in wild life )
sequence of maps is a valid datastructure - yep, but do not mix it with seq of map entries
anyway, we can play further )
(defn assoc-mm [maps k v]
(let [i (->> maps
(map-indexed (fn [i m] (when-not (contains? m k) i)))
(filter identity)
first)]
(if i (update maps i assoc k v) (conj maps {k v}))))
(defn f [x] (if (every? #(instance? clojure.lang.MapEntry %) x)
(reduce (fn [acc [k v]] (assoc-mm acc k v)) [] x)
(into [] x)))
Is there a way to intercept function calls with something like with-redefs
and then call the original function?
(let [orig f] (with-redefs [f (fn [& args] (do-stuff) (orig args))] (body-code)))
like that @stephenmhopper?
Yeah, I had tried that and got a stack overflow, but Iβll give it another shot
(but beware of all the usual caveats around with-redefs
and lazy sequences and threads etc)
user=> (defn foo [x] (println "foo" x))
#'user/foo
user=> (defn bar [x] (foo x) (foo (* 2 x)))
#'user/bar
user=> (let [orig foo] (with-redefs [foo (fn [x] (println "redefined" x) (orig x))] (bar 13)))
redefined 13
foo 13
redefined 26
foo 26
nil
user=>
Interesting. Itβs working now. Iβm not sure what I was doing wrong before. Thank you!