Hey all! Suppose I have a function:
(defn foo [] (cool-stuff :foo :bar :baz))
Is it possible to grab the quoted body of foo
?
(first X) => cool-stuff
(second X) => :foo
Where X
somehow retrieves '(cool-stuff :foo :bar :baz)
using only the var foo
?it’s possible sometimes, unreliably 🙂
You can read the source of a symbol pointing to a var, here is an example code: https://github.com/clojure/clojure/blob/master/src/clj/clojure/repl.clj#L147-L170
then you can read-string
the source
Hmm, maybe this is is a case of the X/Y problem 🙂 What I'm trying to do is write a test that pulls in a form, runs postwalk
on it, and uses that info to run more tests. That way, when the original form is updated, the test will automatically enforce checks against the new changes. I had assumed that the question above was the best way to do it. Is there a better way you might know about? Appreciate the help!
what is the best way to non-destructively prepend a list of elements to another list, sharing the tail of the original list?
concat
? but I don’t understand last part of the question, about sharing the tail
I can write this as a small recursive function of course, which works because I know my lists are small.
(defn append-sharing-tail [l1 l2]
(cond (empty? l1) l2
(cons (first l1) (append (rest l1) l2))))
prepending n elements to a list of length 1 should take the same time as appending n elements to a list of length 1000000000000
and take the same memory
(defn append-sharing-tail [l1 l2]
(cons (first l1) (concat (rest l1) l2)))
and if l1 is empty, that won't work
but I think you meant a recursive call rather than a call to concat, right?
(defn append-sharing-tail [l1 l2]
(cond (empty? l1) l2
(cons (first l1) (append (rest l1) l2))))
no, why you need recursion here?
because the call to concat does not share tails.
why is that?
well if concat shares tails, then I don't even need append-sharing-tail, just call concat directly. right?
right
at least concat is not documented to be tail sharing.
when I look at the code for concat, even though I don't completely understand it, it seems that if the first list is empty, then the second list is returned.
yes, it is
i've been bitten by concat
, especially when the size of the lists are really large.
use lazy sequence carefully
this article https://stuartsierra.com/2015/04/26/clojure-donts-concat
above article really helps me on how to use lazy seq
like (nth (iterate #(concat % [1 2 3]) [1 2 3]) 4000)
; Error printing return value (StackOverflowError) at clojure.core/concat$fn (core.clj:725).
last form returns correct result for me)
and the outcome from mentioned article is not “do not use concat” it is “don’t mix lazy and strict”
the https://clojuredocs.org/clojure.core/distinct doesn't say whether the order is preserved given an ordered sequence. I.e., if a sequence, a
, contains no duplicates is (= a (distinct a))
? Or do I need to check whether the lengths are the same?
If I'm not mistaken, I think it is possible to write a faster uniquification function if I don't have to preserve the order.
Order is preserved (as in all seq ops)
Hi all, is it possible to extract route information from compojure route definition for example in case of these routes to get this data {:route1 "/:study_uuid/study_summary", :route2 "/:study_uuid/study_benchmarks"}. Thanks
(defroutes api-routes
(GET (r-> "/:study_uuid/study_summary") [study_uuid] (get-study-summary study_uuid))
(GET (r-> "/:study_uuid/study_benchmarks") [study_uuid] (get-study-benchmarks study_uuid)))
Let me know if you figure out a way to do this in compojure
, I'm trying to do the same exact thing!
@vnazaryan I'm not sure. Maybe it would be good to look into something like reitit which is data driven rather than macro driven
@vnazaryan, don't see why not, it's just a list you can manipulate
concat will use the original list as its tail, (structurally share) but also it wraps its own lazy thunk around it (which is where the stack bomb of nested concat calls comes in)