Hey guys. How does this function look (generating some fixture data):
(defn- insert-classes! [datasource]
(let [teachers (db/find-by-keys datasource :user {:role (db/enum (:teacher user/roles))} {:columns [:id] :limit 2})]
(doseq [t teachers]
(db/insert-multi!
datasource
:class
[:name :school :description :archived :teacher_id]
(take 5 (repeatedly #(seq
[(first (names))
(first (co-names))
(join " " (take 3 (sentences)))
(rand-nth [true false])
(:user/id t)])))))
(println "Inserted classes")))
Particularly the (take 5 (repeatedly #(seq
part. Is it alright or it can be simplified? Still new to lazy seqs.So the (names)
, (co-names)
etc are all zero-arg side-effecting functions that do ... what?
And why are you calling seq
on the vector?
@somedude314 Can you provide a bit more background on what exactly you're trying to do here?
Consuming this https://github.com/paraseba/faker/blob/master/src/faker/company.cljc#L32
… and this: https://github.com/paraseba/faker/blob/master/src/faker/name.cljc#L41
Because this works for me:
(take 5 (repeatedly #(seq [1 2])))
And this doesn’t:
(take 5 (repeatedly [1 2]))
OK yeah this isn't how lazy-seqs work at all
on each call you are generating a lazy stream of names, and only consuming one, and on the next call you make a new stream
I am basically trying to populate the vector inline for insert-multi!
(repeatedly #(vector 1 2))
Looks like you should map
over the various lazy fakers and make a vector: (map vector (names) (co-names) (map #(str/join " " %) (partition 3 (sentences))) ...)
Then (partition 5 ...)
over that to get groups of five rows each.
What I can do about that when it’s an external library and I only need one name?
(repeatedly #(rand-nth [true false]))
would give you the generator for the archived values in that (map vector ...)
I'd probably create the teacher ID series with (mapcat #(repeat 5 %) (map :user/id teachers))
and that would be the last sequence in that (map vector ...)
-- the fifth and final of the sequence arguments.
That would also cause the number of teachers to control how many groups of 5 rows you got, so it would automatically grow as you changed the :limit
to different values.
and finally (doseq [row-group (partition 5 (map vector (names) ...))] (jdbc/insert-multi! datasource :class [:name :school :description :archived :teacher_id] row-group)
See what I posted in the main channel.
So the key here is to take a series of (infinite) lazy sequences and use map vector
to take corresponding elements from all of them and put them together in rows -- so this in turn would be an (infinite) lazy sequence of rows.
The (partition 5 ...)
and the #(repeat 5 %)
(inside the mapcat
over the teachers) are related so pulling the 5
out of both as a local binding to class-size
or something similar would make sure they stay in sync.
So you can see what I'm taking about on a small scale:
user=> (defn names [] (cycle ["Sean" "Adam"]))
#'user/names
user=> (defn co-names [] (cycle ["ACME" "Saint Mary's" "Collyer's"]))
#'user/co-names
user=> (take 2 (partition 5 (map vector (names) (co-names))))
((["Sean" "ACME"] ["Adam" "Saint Mary's"] ["Sean" "Collyer's"] ["Adam" "ACME"] ["Sean" "Saint Mary's"]) (["Adam" "Collyer's"] ["Sean" "ACME"] ["Adam" "Saint Mary's"] ["Sean" "Collyer's"] ["Adam" "ACME"]))
user=>
Thanks for the detailed input! Will try to put this together and see what I can come up with.
Here's the above with fake sentences added:
user=> (defn sentences [] (cycle (str/split "The quick brown fox jumped over the lazy dog" #" ")))
#'user/sentences
user=> (take 2 (partition 5 (map vector (names) (co-names) (map #(str/join " " %) (partition 3 (sentences))))))
((["Sean" "ACME" "The quick brown"] ["Adam" "Saint Mary's" "fox jumped over"] ["Sean" "Collyer's" "the lazy dog"] ["Adam" "ACME" "The quick brown"] ["Sean" "Saint Mary's" "fox jumped over"]) (["Adam" "Collyer's" "the lazy dog"] ["Sean" "ACME" "The quick brown"] ["Adam" "Saint Mary's" "fox jumped over"] ["Sean" "Collyer's" "the lazy dog"] ["Adam" "ACME" "The quick brown"]))
user=>
(defn- insert-classes! [datasource]
(let [teachers (db/find-by-keys datasource :user {:role (db/enum (:teacher user/roles))} {:columns [:id :email] :limit 2})
class-size 5]
(doseq [row-group (partition
class-size
(map vector
(names)
(co-names)
(map #(join " " %) (partition 3 (sentences)))
(repeatedly #(rand-nth [true false]))
(mapcat #(repeat class-size %) (map :user/id teachers))))]
(db/insert-multi! datasource :class [:name :school :description :archived :teacher_id] row-group)))
(println "Inserted classes"))
Learned a lot, truly appreciated.