Fork me on GitHub
#beginners
<
2016-05-20
>
frankk3850601:05:18

Thank you for the feedback @virmundi. I will give that a try

virmundi01:05:03

Is anyone else having trouble with SublimeRepl in Sub3 not working?

virmundi01:05:35

I'm trying to learn RabbitMQ in Clojure. When I try to get the default exchange binding, the repl locks up. If I do the same thing in a normal terminal repl, it's fine.

victorbjelkholm13:05:44

Hey, I’m trying to get a very simple macro to work but can’t seem to figure it out… I’m declaring my macro like this:

(defmacro print-stuff [to-print] `(println to-print))
and I’m doing
(macroexpand '(print-stuff "Hello World”))
to inspect it, which returns
(print-stuff "Hello World”)
indicating that something is wrong. Calling the macro with
(print-stuff "Hello World”)
yields the error
WARNING: Wrong number of args (1) passed to clojulator.ns/print-stuff at line 1 <cljs repl>
. I’m sure I’m missing something super obvious...

victorbjelkholm13:05:15

Oooooh, yeah, that’s true, didn’t think about the macros working differently in clojurescript/clojure… Thanks a bunch @mfikes

victorbjelkholm13:05:24

@mfikes: yeah, trying it in the clojure repl and it works fine

mfikes13:05:39

@victorbjelkholm: Cool. You added ~ in front of to-print, right?

victorbjelkholm13:05:17

@mfikes: nope, you need it for all the arguments?

victorbjelkholm13:05:40

yeah, apparently...

victorbjelkholm13:05:55

didn’t try executing it, just expanding the macro. But you’re right. Thanks for that heads-up

mfikes13:05:26

@victorbjelkholm: Yes, read up on how syntax-quote works. 🙂

mattsfrey14:05:37

Say I have a list of address books, some of them are of type “mail” an some of type “social” (both inside the same list), every mail account has a corresponding social where they share the key “alias", and I want to loop through every book of type mail, find it’s social book, and map them both into a new list paired as keys in a map. What is the most efficient / elegant way to do this? My current solution:

roberto14:05:01

hmmm, something like this is probably better solved by specter https://github.com/nathanmarz/specter

mattsfrey14:05:51

interesting library, but I’d prefer to just do vanilla clojure if possible really

bronsa15:05:59

it's a pain to traverse/update deeply nested data structures in pain clojure, spectre/traversy really help

mattsfrey15:05:00

another question, when doing an assoc-in db and passing it a map, it’s literally storing the map function in the db, how do you get it to store the evaluated map?

featalion16:05:31

evaluate lazy sequence by doall

agile_geek17:05:45

@mattsfrey: this is a common "don't" in Clojure - mixing side effects with lazy operations e.g. I/O and results of map. See this article: https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects

mattsfrey18:05:42

@agile_geek: very informative article, thanks

agile_geek18:05:52

@mattsfrey: You're welcome. All of @stuartsierra's articles are worth a read.

mattsfrey18:05:48

another quick Q. Is this valid? Like will c actually be assigned from the result of b’s assignment? (I’m guessing not. and if not, what would be the best method for doing this?)

(map (fn [i] {:a i :b (do-some-calc i) :c (do-some-calc :b) }) items)

rauh18:05:34

@mattsfrey: Put the value (do-some-calc i) into a let binding. Then use it twice (once to assign to :b, once to do some more calculation)

mattsfrey18:05:07

i was thinking of that, the let statement would literally go inside the map function before the return?

agile_geek19:05:33

@mattsfrey: In a map you are only going to have one value per key and each key is unique.

agile_geek19:05:48

So you just look up the value using the key

mattsfrey19:05:25

it’s a list of maps where two maps in the list will share a key-value pair

agile_geek19:05:34

i.e. in your example you can only have one :alias key in your map

agile_geek19:05:09

You could use drop-while to drop the items in you list that don't include the required map and then take the first from the lazy sequence produced but it's not more efficient or really any more idiomatic than filter.

agile_geek19:05:58

(def my-maps [{:fred "fred"} {:alias "alias1" :val1 "val1"} {:alias "alias1" :val2 "val2"}])

(first (drop-while (fn [m] (not= (:alias m) "alias1")) my-maps))

agile_geek19:05:43

BTW your code should read:

(first (filter #(= (:alias %) "my-alias") abs))

agile_geek19:05:02

@mattsfrey: Your other fn that needed the let binding would look something like this:

(map (fn [i] (let [b (do-some-calc i) c (do-some-calc b)] {:a i :b b :c c })) items)
You can't embed the let in the middle of the map literal.

agile_geek19:05:37

Also the easiest way to work this stuff out is start a REPL and try it out.

mattsfrey20:05:26

yeah that^ was actually what I meant

agile_geek20:05:09

BTW your filter thing could also be done using some:

(some (fn [m] (when (= (:alias m) "my-alias") m)) abs)

jswart20:05:36

I was trying to code up how I would do it, but I’m fairly busy.

jswart20:05:48

In short, you are doing the update and the selection at the same time.

jswart20:05:14

Separating these two would make it easier and more readable.

jswart20:05:42

It would be easier to 1. get the data. 2. Transform the data 3. put the new data back.

jswart20:05:58

once you have those steps then you can use -> / ->> for readability

jswart20:05:25

I would select things up like this `(group-by first (map (juxt :alias :val1 :val2) [{:alias 1 :val1 2} {:alias 1 :val2 7}])) `

jswart20:05:30

(group-by first (map (juxt :alias :val1 :val2) [{:alias 1 :val1 2} {:alias 1 :val2 7}]))

jswart20:05:44

then use the values of the result of that to make my updated/merged forms

jswart20:05:51

then put it back into the db

mattsfrey21:05:39

great insights, thanks