Fork me on GitHub

Is there a way to "arrange" the order of a key in a hash-map? I'm building a service which returns JSON, and I want to have control on which field gets displayed first in the JSON (e.g. I don't want the "id" and "type" field to be hidden somewhere in the middle of a dense object).


Will creating a type/record do the trick?


The order of the key in JSON will likely depend on which library you are using to encode it from Clojure. You might get away with using a sorted-map


I'm using ring-json, which uses cheshire


You might be able to get away with something like this:

(into (array-map :id 17 :type "some-type")
      {:an "unordered" :map "to dump in"})


Well, I guess I'll stick to the randomness then. I'm not going to convolute my function with that. I appreciate your inputs though @noonian


@hawari.rahman17 if you use Jsonista (or something else that allows access to the underlying Jackson stuff), you can use Jackson to do this:

(ns foo
  (:require [jsonista.core :as json]
  (:import [com.fasterxml.jackson.core JsonGenerator]
           [com.fasterxml.jackson.databind SerializationFeature]

(def object-mapper
    (.configure SerializationFeature/ORDER_MAP_ENTRIES_BY_KEYS true)

(defn encode [event]
  (json/write-value-as-string event object-mapper))


although, I just realized that you want them sorted in a custom order, not alphabetically... my bad opieop


No problem. Thanks anyway for taking notice of this, gave me another perspective on what can be done.


No problem. Thanks anyway for taking notice of this, gave me another perspective on what can be done.


CLJS related question


Can anyone tell me why this fails trying to call on null


(defn Get [url fun] (req/get url #((fun %2))))



(defn Get [url fun] (req/get url #(fun %2)))
(i've remove one parenthesis from the anonymous function call)


That worked, stupid me and stupid paren...

👍 4

while this just works fine ?


(defn Get [url fun] (req/get url fun))


Hi guys! How can I update a value inside a atom vector of maps? For example:

(def var (atom [{:a 1 :b 2} {:a 2 :b 2}]
and now I want to update the {:a 2 :b 2} to {:a 2 :b 3} Is there any easy way to do this? My first thought was to remove the element from the vector and then add it again


u can use update-in or assoc-in


but how can i select the array element that I want to update?


u can use the index of the element of vector u want to update, like (assoc-in [{:a 1 :b 2}] [0 :b] 3) => [{:a 1 :b 3}]


vectors are associative data structures of index->value. it’s reallly useful to remember that. it’s often why I stick to vectors instead of lazy seqs.


Is there a way to destructure varargs on type? This works but seems unreadable:

(defn myfun
 [x y & args]
 (let [tooltip (some #(when (string? %) %)
       mykey   (or (some #(when (keyword? %) %)
   (do- stuff)))
What would be an idiomatic way to do this?


@magra Hrm. If that last argument were instead a map, you could use map destructuring to pull out what you want. It seems tricker to algorithmically cope with a list of typed args...


I guess you could have a string or keyword anywhere in that list.


@mfikes Maybe I will just write a function like string? that returns the string instead of boolean.


like get-first-string.


It would not be destructuring but readable.


Yeah, you could then use juxt to destructure as in

(let [[tooltip mykey] ((juxt first-string first-keyword) args)]


But, to be honest, I would just let tooltip and mykey


(get-first seq string? :default)




Yeah, that looks better


Make a reusable little fn


Why does the first example here work and the second one not?

(defn sitemap
  (def host (get (liburl/url url) :host))
  (def anchors (-> url
                   client/get :body
                   hickory/parse hickory/as-hickory
                   ((partial select/select (select/tag :a)))))
  (map :attrs anchors))
(defn sitemap
  (def host (get (liburl/url url) :host))
  (def anchors (-> url
                   client/get :body
                   hickory/parse hickory/as-hickory
                   ((partial select/select (select/tag :a)))
                   (map :attrs)))

Alex Miller (Clojure team)13:03:27

Generally, you should never use def inside a defn - those create global vars with scope beyond the function


oops, that's good to know. Thanks!

Alex Miller (Clojure team)13:03:11

on the second one not working, you’re using -> which is thread-first

Alex Miller (Clojure team)13:03:34

so it will effectively do (map anchors :attrs)

Alex Miller (Clojure team)13:03:05

in this case if all the other functions are single arg, you can just switch to ->>


Supposing they weren't, how do I get around this? define a lambda that calls map with the args reversed or a partial function using map?

Alex Miller (Clojure team)14:03:01

I probably just wouldn’t use a thread macro to combine those two sets of calls


you could use a thread-last at the end of the thread-first (-> url client/get ... (->> (map :attrs)))

Alex Miller (Clojure team)14:03:32

I find mixing them is generally harder to read than not using them at all


though it’s not the most elegant approach

Alex Miller (Clojure team)14:03:42

and as-> can be used in some cases


I think this function might be guilty of doing too much

Alex Miller (Clojure team)14:03:32

-> works best on a series of functions that take and return collections (maps, vectors, etc) - functions like conj, merge, assoc, etc

Alex Miller (Clojure team)14:03:58

->> works best on a series of functions that take and return sequences - functions like filter, map, reduce, etc

Alex Miller (Clojure team)14:03:13

b/c all collection functions take the collection first and all sequence functions take the sequence last

Alex Miller (Clojure team)14:03:27

I think the scope of your function is fine

👍 4

just use let bindings to structure things rather than trying to force it all into a thread-first macro?

Alex Miller (Clojure team)14:03:13

I find the ((partial select/select (select/tag :a))) hard to read too and maybe not worth including in that threaded expr


Yeah I think pulling it apart some would help. Thanks for your time and expertise


can a defmethod be dispatched based on matching one of N values? i have a mutimethod that dispatches on a map key that represents a frequency of an event (:daily, :weekly, :monthly, :yearly [or :annual, :annually]). it is the "yearly or annually or annual" set of values that I would like to handle in a single defmethod handle.

Alex Miller (Clojure team)16:03:03

you can’t define it directly in this way, but you can define multiple defmethods that invoke the same function - some people have macro’ed that up to avoid the duplication

Alex Miller (Clojure team)16:03:16

or you can leverage multimethods ability to create arbitrary keyword hierarchies

Alex Miller (Clojure team)16:03:51

then you’d have a “parent” keyword and just define one method on that


ah, ok, had not consider that. thank you.


I like implementing a defmethods macro — but it’s simpler to leave the defmethod dispatch duplication while handling the logic duplication with a separate function


@bjr @alexmiller thank you both for the feedback. i had considered moving the logic duplication to a function defined outside the multimethod hierarchy, but was seeking for a way to avoid that. will try the keyword hierarchy after grokking it. thanks again.

👍 4

are the clojure koans a good way to start?


@guilhermelionribeiro A lot of people like them as a starting point. Also check out Clojure for the Brave and True.

👍 4

Hi guys, why do the following return the same result:

(clojure.string/split "a_b" #"_")
(clojure.string/split "a_b_" #"_")


In the second case, I expect ["a" "b" ""] instead of ["a" "b"]


@ahmadnazir by default trailing empty strings are discarded


Thanks! I didn't find that obvious from the documentation but now that you explain it, it makes sense.


yeah, unfortunately the docstring doesn't mention it


it uses the Java string split internally, so i looked at the Java docs


i'll ask in #clojure-dev to see if the docstring can be updated

Alex Miller (Clojure team)20:03:40

I believe this behavior has changed in Java since the function was originally written


ah, i see. that makes sense.


@alexmiller want me to file a Jira?

Alex Miller (Clojure team)20:03:55

sure. there might be one so do a search

Alex Miller (Clojure team)20:03:04

I vaguely recall this coming up before


ok, will do


ah, yeah. it's CLJ-1360


and also CLJ-1857 i guess

Alex Miller (Clojure team)20:03:26

Thanks, I incorporated the changes from CLJ-1857 into the CLJ-1360 patch and closed 1857

metal 8
Alex Miller (Clojure team)20:03:38

will try to get that closed in 1.10


great, thank you! 🙂


pass -1 as the limit to get them back:

=> (clojure.string/split "a_b_" #"_" -1)
["a" "b" ""]

metal 8
Michael Fiano20:03:14

Does anyone here have any Common Lisp experience? I'm trying to figure out an idiomatic way to map a basic snippet of code to Clojure


I've used common lisp ~6 years ago but ask away, I'm sure that if I can't somebody else will be able to answer

Michael Fiano20:03:26

I'd like a function that maps over a few different ranges of numbers, and puts them all into a flat sequence of numbers, like this:

Michael Fiano20:03:50

This is mutating the same lexical results list. I need a functional/clojure way to do the same within the same function

Michael Fiano20:03:53

So given (range 0 5), (range 0 3), and (range -3 1), this theoretical function would return (0 1 2 3 4 0 1 2 -3 -2 -1 0)


(partial apply concat) returns a function that does that

Michael Fiano20:03:44

The best I can think of is nested fors with flatten


yeah i think for is the way to go here, though you never need to nest fors


for takes multiple bindings, and you can do :when and :let inside the bindings vector


(for [x [1 2 3]
	  y [4 5 6]
	  :let [foo (+ x y)]
	  :when (> foo 7)]
  [x y])
([2 6] [3 5] [3 6])


and then you could apply concat that to collate them


=> (concat (range 0 5) (range 0 3) (range -3 1))
(0 1 2 3 4 0 1 2 -3 -2 -1 0)


oh yeah, that's just concat

Michael Fiano20:03:00

Ok, well, that is the basic idea, although like the linked code, this function would be a HOF that calls a function on each number, and puts that in the returned sequence instead of the number.

Michael Fiano20:03:06

Sorry I left that part out

Michael Fiano20:03:57

also has a conditional to see if it even will call the function or just skip the number


if you need to include some numbers and exclude others, combine it with filter

Michael Fiano20:03:12

That's just map + concat right? I need to map several times


what do you mean "map several times"? I don't quite follow you there


(into [] (comp cat (map f)) [coll1 coll2 ... colln])

Michael Fiano20:03:13

The idea is I'm collecting a list of neighbor cells of a 2D grid given an origin. If I were for example to collect a cross shape with an arbitrary size, I'd need to map from left to right, then from top to 1 above origin. and then 1 below origin to bottom, in order to skip processing the origin twice (because it already was with the left to right pass)


depending on the task, I would probably use a flat array to store matrix and generate the indices I need


or maybe even use something like core.matrix if you need more advanced operations

Michael Fiano20:03:52

Thanks. I'm porting that whole file that I linked, and that is the last function to write. It's basically a kernel for convolution-based image processing


Oh, ok, so you're using nested vectors?

Michael Fiano21:03:58

I'm not sure what you mean.

Michael Fiano21:03:16

(defmethod collector :horizontal [_]
  (fn [{[_ max-extent] :extent :as kernel} f]
    (for [x (range (- max-extent) (inc max-extent))
          cell (neighbor-cell kernel x 0)
          :when cell]
      (f cell))))
Here is my function for processing a horizontal strip of cells given an origin. It's easy because there is no sparsity or multiple collections.


Hmm, I'm not sure I understand it completely (sorry). What 'neighbor-cell' returns?

Michael Fiano21:03:52

a record or nil


You sure you didn't mean :let [cell (neighbor-cell ...)] then? Bindings in for work like a nested loop


So you're iterating over whatever neighbor-cell returns, binding each result to cell


Aha, ok then. So basically your 'neighbor-cell' returns the cell given x and y


So you need to generate x,y coordinates for the cross shape

Michael Fiano21:03:16

It could also return nil, hence the :when

Michael Fiano21:03:42

Yeah and those coordinates are 3 different collections

Michael Fiano21:03:10

left to right. top to 1 above origin. 1 below origin to bottom.


Can't you just call range to generate basically two strips: one horizontal (x is fixed, y is (range start end)), one vertical (y is fixed, x is (range start end))?

Michael Fiano21:03:25

I could but 1 of those strips needs to be split, so 3 total.

Michael Fiano21:03:32

otherwise I am processing the middle cell twice


Well yeah, but you'll concat everything together anyway, so no big deal?

Michael Fiano21:03:53

Yeah I guess I'm just a newbie. I can create those 3 collections with a single for with 3 different bindings?


I'd do something like (map vector (repeat x-of-origin) (range (- y-of-origin size) y-of-origin)) - it will give you a vertical strip above the origin


a seq of vectors


then the same for the strip below the origin, then for the horizontal strip


then concat everything together and map\filter as you wish

Michael Fiano21:03:16

Ah nice. That seems easy enough. Thanks


Well, or you can apply "for" to get a full square around your origin, but you'll need to filter out the indices that don't fall into the cross anyway, so I'm not sure it'll be more concise.


Glad if it helps!


Hello all! 🙂 Extremely new here. Im wondering why I get the space between "John" and "!" in my output. => ((fn [name] (println "Hello, " name "!")) "John") Hello, John !


@gryclmn: println adds spaces between args


ha! How can I avoid this? I also apologize for not wrapping the code as "code", just saw that ability, new to Slack


@mfiano: sounds like what you need is two steps, generating x/y pairs, then doing something with each pair

Michael Fiano21:03:17

Thanks. I'll think about it. I'm actually porting that whole file that I linked, and this is the last function to write.


@gryclmn: you can create a string with str then call println on that

👍 4

=> (str "Hello, " "John" "!")
"Hello, John!"
=> (println (str "Hello, " "John" "!"))
Hello, John!

👍 4

@noisesmith Thank you very much!

Michael Fiano22:03:26

(defn testfn []
  (map vector (range 0 5)))
Why would this give a NullPointerException when called if defined in a package, but not in the REPL?

Alex Miller (Clojure team)22:03:19

should be ok either place. can you share the NPE output?

Alex Miller (Clojure team)22:03:52

looks like that error is coming out of slamhound, not your code

Alex Miller (Clojure team)22:03:47

well, I guess not, that’s just in the middleware

Michael Fiano22:03:56

odd. it's the same function defined in a package and the REPL. when called with the fully qualified package name it errors, but works fine with the REPL package

Alex Miller (Clojure team)22:03:19

oh, it’s picking up mfiano.crawler.kernel/map not clojure.core/map

Alex Miller (Clojure team)22:03:34

so map means something different in the namespace

Michael Fiano22:03:48

Oh I might have some funky refers going on there. Thanks

Alex Miller (Clojure team)22:03:09

yeah, be careful overlapping clojure.core fns :)