This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-11
Channels
- # announcements (1)
- # aws (2)
- # beginners (140)
- # boot (67)
- # cider (50)
- # clojure (64)
- # clojure-berlin (1)
- # clojure-conj (1)
- # clojure-france (2)
- # clojure-italy (2)
- # clojure-nl (8)
- # clojure-norway (6)
- # clojure-seattle (1)
- # clojure-spec (81)
- # clojure-sweden (2)
- # clojure-uk (131)
- # clojurescript (147)
- # clojutre (7)
- # cursive (40)
- # datomic (34)
- # editors (5)
- # emacs (7)
- # events (9)
- # figwheel (18)
- # figwheel-main (1)
- # fulcro (2)
- # instaparse (1)
- # jobs (3)
- # leiningen (1)
- # luminus (10)
- # lumo (1)
- # mount (6)
- # off-topic (12)
- # pedestal (4)
- # portkey (7)
- # re-frame (8)
- # reagent (21)
- # reitit (10)
- # ring-swagger (5)
- # shadow-cljs (140)
- # specter (4)
- # tools-deps (53)
- # uncomplicate (1)
Seems like data/objects are more so isy, whereas functions/verbs are more about the usage, right?
Hi! I'm working with a sequence of maps that contain other maps and I want to map some of the nested values into a flat table. The code looks like this:
(clojure.pprint/print-table
(->> failed-jobs
(map #(select-keys % [:name :duration :id :runner]))))
The runner key holds a map where I'm only interested in the runners name. How do I map that into my flat structure?can you post a sample of expected input/output? that makes it easier to understand what’s going on (at least for me 😄 )
Input:
{:name "job name"
:{runner {:description "runner description"}
:duration "111.1"
}
;; And a LOT of unwanted keys
Desired output:
"job name", "runner description", "111.1"
Clojure @ Apple? Naisssssssssss https://jobs.apple.com/search?job=113230158&openJobId=113230158#&ss=Clojure&t=0&so=&pN=0&openJobId=114084463 https://media.giphy.com/media/pCO5tKdP22RC8/giphy.gif
i have a question 🙂 i need to convert a seq of key-value tuples into a map of key to value-seq/a multimap (keys are not unique) so far, i have the following code:
(def key-val-seq [[1 :a] [1 :b] [2 :c] [3 :d] [4 :e] [4 :f]])
(->> key-val-seq
(group-by first)
(map (fn [[k v]] [k (map second v)]))
(into {}))
;; => {1 (:a :b), 2 (:c), 3 (:d), 4 (:e :f)}
it works, but i don't really find it elegantany suggestions how to improve this?
@timo.freiberg I think it’s already fine. reduce-kv also works:
(->> key-val-seq
(group-by first)
(reduce-kv
(fn [acc k v]
(assoc acc k (mapv second v)))
{}))
thanks, I didn't know about reduce-kv!
I'd probably just do something like:
(reduce (fn [m [k v]] (update m k conj v)) {} key-val-seq)
Or if you need to preserve the original value order in the map vals, replace conj
with (fnil conj [])
@michael.gaare wow. Didn't know about fnil
func. Was writing the update-or-default
function and using it 😅
Yep, I've done that before. The discovery of fnil
(thanks to Stuart Sierra actually) was one of those golden moments
4clojure is a nice resource to learn about the core functions.
very good recommendations from everyone 🙂
what’s the basic template for using loop
and tail-recursion with an accumulator to process one element at a time?
usually reduce does that simpler - since it automates consuming a sequence
(def myitems ["one" "two" "three" "four"])
(loop [input myitems acc []]
(when (not-empty input)
(println acc)
(recur (rest input) (conj (first input) acc))))
this loop works fyi, you just need to put the args to conj
in the right order: (conj acc (first input))
(reduce (fn [acc el] (conj acc el)) [] myitems)
or (reduce conj [] myitems)
if you always consume in order, reduce is simpler
your args to conj are reversed in that example, btw
so, if I want to do a bunch of things on each array element, I would use (do (things))
in the anon fn body?
anon fns already have an implicit do
as long as you use fn
and not #()
no - because the result of conj is being thrown away
(reduce (fn [acc el] ... (conj acc el)) [] myitems)
if i have a multimethod with a dispatch fn that returns a vector, like (defmulti foo (juxt :role :shirt-color))
(or something), how can i set the :hierarchy
option if the values will come from two different hierarchies?
if you need to reuse things use a let, sure
thanks @noisesmith
your original is the way to do it with loop - if you fix the conj call
loop is messier and it's nice to use something special purpose though
or another way to put it is that there's more ways to make mistakes with loop
Regarding my loop. I’m working on brave and true ch3 prob5. I have this (which works):
(def asym-hobbit-body-parts [{:name "head" :size 3}
{:name "left-eye" :size 1}
{:name "left-ear" :size 1}) ; and so on.
(reduce (fn [acc part]
(let [n1 {:name (clojure.string/replace (:name part) #"^left-" "c1-")
:size (:size part)}]
(conj acc n1))) [] asym-hobbit-body-parts)
what’s a clojure-y way to basically rename #“^left-” to c1- through c5-?(reduce (fn [acc part]
(for [x [ 1 2 3 4 5]]
(let [n1 {:name (clojure.string/replace (:name part) #"^left-" (str "c" x))
:size (:size part)}]
(conj acc n1)))) [] asym-hobbit-body-parts)
^ doesn’t work. I think I’m not returning the for output?in C like languages for is a looping control structure, in clojure for is a list comprehension
@jm.moreau hint - you can use for
to iterate+bind more than a single sequence
what I know is ugly is this :
(reduce (fn [acc part]
(let [n1 {:name (clojure.string/replace (:name part) #"^left-" "c1-")
:size (:size part)}
n2 {:name (clojure.string/replace (:name part) #"^left-" "c2-")
:size (:size part)}] ; and so on up to "c5-"
(conj acc n1 n2))) [] asym-hobbit-body-parts)
:size
is not a valid binding name
@noisesmith it’s in a hashmap
oh, so it's just bad indentation, I missed that
yes, I want to take something like “left-foot” and create “c1-foot” “c2-foot” … “c5-foot”
@jm.moreau as a further hint, try putting this in your REPL: (for [x ["a" "b" "c"], y (range 1 6)] [x y])
I'd take a look at (doc for)
while you're at it https://clojuredocs.org/clojure.core/for
@jesse.wertheim thanks, yea. for
makes sense and this would work:
(for [c (range 1 6)] (str "c" c "-"))
what trips me up is how to build up my accumulator and scopingwhy would you need an accumulator for this?
I proposed using reduce thinking an accumulator was actually needed, but if results are sequential in input order, use for or mapcat instead
you don't need map over for, for is a list comprehension and can do that on its own
(or mapcat can also do this, without needing for)
if you just want a pipeline with a final (vector, or other non-lazy) result, the optimized way would be into and mapcat
If I run lein cljsbuild once
on my local machine. It builds it just fine with no warning or errors. but when Jenkins builds it using the same command I am getting a plethora of warnings and the build fails eventually.
yeah, the name can be misleading
so the assumption is: something is different when jenkins is building from when you are building
for example: do you have some plugin enabled that jenkins doesn't have? or do you have stale artifacts that are messing with the build? are you and jenkins actually building the same code? (different branches, uncommitted changes, etc)
my guess would be a stale artifact or a different branch, but that is just a wild guess
have you pushed all your changes? have you pulled any outstanding changes? is it the same commit?
does your jenkins build start out with a clear workspace or is it littered with the detritus of a previous build?
I am under the assumption it is starting off with a clean workspace as the logs show it deletes the previous workspace
the idea being you could have some uncommitted change or some git ignored file or something in your checkout that is making the build pass
It generally removes stuff in your target
directory (but I think it is configurable as to what it removes). The idea is to put your project back to a pristine state.
But, that may fail to repro what your CI system is doing, so as @hiredman suggests, it is best to clone into a new directory and try building from there.
Another place where you can get state that isn't cleaned up, even by cloning to a new tree is if you have :aot-cache
enabled. https://clojurescript.org/reference/compiler-options#aot-cache
hmm so it looks like lein clean
was purely coincidental as to why the build started failing again on my local box
The Jenkins build was failing as it should. Valid errors and all. But my local build was passing and I didn't (still don't) understand why
Another source of things working on one box but not another if is the requires are wrong but just happen to work out by chance when :parallel-build
is set to true
Just ran ag
on :parallel-build
and no instance was found. So I guess it safe to say we are not using that
Lets pretend that someone is using macOS and they want to install clojure CLI tools (not the JAR) without Homebrew. How would one go about doing this?
the generic linux instructions should work
Great. I wasn’t sure if there was something linux specific in there
the shell script is pretty short so it is easy to verify - nothing I can see is linux specific if you have the prerequisite tools they list
(bash, curl, rlwrap, java)
oh you might also need gnu - n/m I have it installed for some reason but osx comes with its own versioninstall
I will give it a shot of a fresh macOS
I think the gotchas will be rlwrap and java - not hard things to acquire