clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2020-09-19T03:39:13.109800Z

Dear all, is it possible to get body of a function as string, then I'd like to print the function body. Thanks.

the2bears 2020-09-19T15:38:15.123900Z

What's your use case? Functions in code you've written, or otherwise?

2020-09-19T03:47:33.110300Z

source?

2020-09-19T03:58:02.111Z

source will do that if the body of the function is stored in a file, and its definition was loaded from the file.

2020-09-19T03:58:28.111500Z

Clojure does not otherwise save the body of functions as anything other than their compiled byte-code format.

2020-09-19T03:59:07.112200Z

one could modify Clojure to save functions in other forms than that, but it does not do so as implemented today.

2020-09-19T14:18:36.113800Z

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

jsn 2020-09-19T14:25:13.114600Z

@ivana (f (lazy-seq (mapcat seq [{:a 1} {:b 2} {:c 3}]))) ? πŸ™‚

2020-09-19T14:28:42.115300Z

@jason358 yep, seq of map entries should be a map )

2020-09-19T14:29:50.115800Z

even if (f (lazy-seq (mapcat seq [{:a 1} {:a 2} {:a 3}]))) πŸ™‚

2020-09-19T14:32:46.116500Z

moreover, if (*f* (*lazy-seq* (*concat* (*seq* {:a 1 :stuck_out_tongue: 2 :c 3}) [[:d 4]]))) πŸ™‚

2020-09-19T14:40:52.117300Z

but for last case one can use

(defn f [x] (into (if (every? #(instance? clojure.lang.MapEntry %) x) {} []) x))

dpsutton 2020-09-19T14:49:53.117500Z

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}

2020-09-19T14:52:29.117900Z

(set [1 1 1 1 1 1])
#{1}

dpsutton 2020-09-19T14:54:02.119300Z

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

2020-09-19T14:57:49.122200Z

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 )

2020-09-19T14:59:32.123100Z

sequence of maps is a valid datastructure - yep, but do not mix it with seq of map entries

2020-09-19T15:15:27.123600Z

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

stephenmhopper 2020-09-19T22:17:27.125200Z

Is there a way to intercept function calls with something like with-redefs and then call the original function?

seancorfield 2020-09-19T22:31:52.126300Z

(let [orig f] (with-redefs [f (fn [& args] (do-stuff) (orig args))] (body-code))) like that @stephenmhopper?

stephenmhopper 2020-09-19T22:32:26.127100Z

Yeah, I had tried that and got a stack overflow, but I’ll give it another shot

seancorfield 2020-09-19T22:32:41.127500Z

(but beware of all the usual caveats around with-redefs and lazy sequences and threads etc)

seancorfield 2020-09-19T22:35:22.127900Z

@stephenmhopper

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

stephenmhopper 2020-09-19T22:36:56.128300Z

Interesting. It’s working now. I’m not sure what I was doing wrong before. Thank you!