beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Dave Russell 2020-10-09T08:59:09.070600Z

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?

vlaaad 2020-10-09T09:01:22.071500Z

it’s possible sometimes, unreliably 🙂

vlaaad 2020-10-09T09:04:08.072300Z

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

vlaaad 2020-10-09T09:05:02.073100Z

then you can read-string the source

Dave Russell 2020-10-09T09:10:17.075600Z

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!

Jim Newton 2020-10-09T09:42:05.076200Z

what is the best way to non-destructively prepend a list of elements to another list, sharing the tail of the original list?

2020-10-09T09:45:53.077Z

concat ? but I don’t understand last part of the question, about sharing the tail

Jim Newton 2020-10-09T09:46:34.077700Z

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

Jim Newton 2020-10-09T09:47:36.077800Z

prepending n elements to a list of length 1 should take the same time as appending n elements to a list of length 1000000000000

Jim Newton 2020-10-09T09:47:51.078Z

and take the same memory

2020-10-09T09:48:00.078200Z

(defn append-sharing-tail [l1 l2]
  (cons (first l1) (concat (rest l1) l2)))

Jim Newton 2020-10-09T09:48:37.078400Z

and if l1 is empty, that won't work

Jim Newton 2020-10-09T09:49:02.078600Z

but I think you meant a recursive call rather than a call to concat, right?

Jim Newton 2020-10-09T09:49:19.078800Z

(defn append-sharing-tail [l1 l2]
  (cond (empty? l1) l2
        (cons (first l1) (append (rest l1) l2))))

2020-10-09T09:49:19.079Z

no, why you need recursion here?

Jim Newton 2020-10-09T09:49:40.079200Z

because the call to concat does not share tails.

2020-10-09T09:50:01.079400Z

why is that?

Jim Newton 2020-10-09T09:50:23.079600Z

well if concat shares tails, then I don't even need append-sharing-tail, just call concat directly. right?

2020-10-09T09:50:47.079800Z

right

Jim Newton 2020-10-09T09:51:01.080Z

at least concat is not documented to be tail sharing.

Jim Newton 2020-10-09T09:54:20.080400Z

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.

2020-10-09T09:54:50.080600Z

2020-10-09T09:55:30.081200Z

yes, it is

mavbozo 2020-10-09T10:19:23.081400Z

i've been bitten by concat , especially when the size of the lists are really large.

mavbozo 2020-10-09T10:19:37.081600Z

use lazy sequence carefully

mavbozo 2020-10-09T10:19:48.081800Z

this article https://stuartsierra.com/2015/04/26/clojure-donts-concat

mavbozo 2020-10-09T10:20:14.082100Z

above article really helps me on how to use lazy seq

mavbozo 2020-10-09T10:20:36.082300Z

like (nth (iterate #(concat % [1 2 3]) [1 2 3]) 4000)

mavbozo 2020-10-09T10:20:49.082500Z

; Error printing return value (StackOverflowError) at clojure.core/concat$fn (core.clj:725).

2020-10-09T10:32:28.082800Z

last form returns correct result for me)

2020-10-09T10:35:43.083Z

and the outcome from mentioned article is not “do not use concat” it is “don’t mix lazy and strict”

Jim Newton 2020-10-09T13:27:33.085300Z

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?

Jim Newton 2020-10-09T13:29:41.086Z

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.

alexmiller 2020-10-09T13:53:18.086700Z

Order is preserved (as in all seq ops)

Karo 2020-10-09T15:01:20.089700Z

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

Dave Russell 2020-10-11T09:46:42.138700Z

Let me know if you figure out a way to do this in compojure, I'm trying to do the same exact thing!

borkdude 2020-10-09T18:52:56.090300Z

@vnazaryan I'm not sure. Maybe it would be good to look into something like reitit which is data driven rather than macro driven

👍 1
Nassin 2020-10-09T19:23:46.091Z

@vnazaryan, don't see why not, it's just a list you can manipulate

👍 1
2020-10-09T21:35:50.091500Z

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)