Fork me on GitHub
#beginners
<
2017-04-24
>
drewverlee00:04:55

@ghadi Ah ok. I temporarily forgot he was giving reverse advice.

drewverlee00:04:55

is there a reasonable way to compose a function signature? I would like to dispatch to a function if it has the necessary arguments and it would be nice if i didn’t have to specify those twice, once in the signature of the method and then again in the dispatch function. Also, its amazing that that works.

(defmethod get-tags
  #(clojure.set/superset? % :base-url :repo :image :user :password)
  [{:keys [:base-url :repo :image :user :password]}]
  (-> (client/get (str base-url "/api/" repo "/v2/" image "/tags/list") {:basic-auth [user password]})
      (get :body)
      (json/read-str)
      (get "tags")))

drewverlee00:04:20

or possible that isn’t working

drewverlee00:04:27

and i need to refresh my repl 😕

drewverlee00:04:42

ok, yea. clearly you cant specify a function as the dispatch value, but i feel like it would be awesome if you could. Why doesn’t this wizardry exist? Too slow?

drewverlee01:04:28

its like a que

drewverlee01:04:39

i should probably just use a que

vitruvia02:04:35

I mean... is it assigning the values of both varibles at the same time?

noisesmith02:04:50

there's no assignment - you are creating an arg to recur

noisesmith02:04:45

but pop is a silly way to reverse, because different collections pop from different directions

vitruvia02:04:08

but how is there no assignment. Even if I'm not assigning anything, the function has to, doesn't it?

vitruvia02:04:21

isnt that what I'm telling it to do with loop?

noisesmith02:04:46

your declaring the bindings for the next recursion

noisesmith02:04:25

it's just as if you did (defn foo [a b] ... (foo (f a) (g b))) - except the recur form ensures you don't use stack

vitruvia02:04:05

ok I think I get it

vitruvia02:04:29

by the way, how would you do the reversion?

noisesmith02:04:09

I'd use first / rest instead of peek / pop since first and rest are guaranteed to work from the correct end of the collection

noisesmith02:04:36

or, I would simply put the data into a new collection that builds up in the right direction (too clever for #beginners I think)

vitruvia02:04:14

yeah I still haven't learned that xD

vitruvia02:04:20

well now I have I guess

noisesmith02:04:36

you saw conj right? into repeatedly uses conj on each input to attach to the output as it builds it up

vitruvia02:04:43

so it is basically what I did but you used () to ensure it behaves as you want?

noisesmith02:04:21

into is a lot like a loop that uses conj - it has some other features too (including optimizations, and it takes a transducer arg to transform inputs too if needed)

vitruvia02:04:16

I think I understand most of what you said... I'm not sure what a transducer arg is but I get the overall idea of into

noisesmith02:04:29

that it transforms the input should suffice for now

vitruvia02:04:03

Yes. Thank you!

john02:04:16

oh that's fancy

noisesmith02:04:56

I don't think they are good #beginners material, but transducers are good for isolating data transformation from data context, using them well improves code quality a lot in my experience

john02:04:44

Yeah, it looks concise. But the point is that it is more efficient, right? It's not generating the sequence twice.

noisesmith02:04:31

or five times eg. (comp (map f) (filter pred?) (mapcat g) (take N) (partition-all 3))

noisesmith02:04:07

if you use the regular functions, each one creates intermediate collections, as a single composed transducer, only one collection need be created (if any) - the consumer of the transducer takes care of that

john02:04:30

That's pretty fantastic

noisesmith02:04:55

that's not the only point though - they reduce complexity by isolating what you do with the data from the place the data comes from and where you put it

noisesmith02:04:11

which incidentally eliminates the creation of lazy-seqs you don't need, but it also simplifies code

john02:04:27

Writing your own transducers from scratch is what makes me flinch a bit. The stateful variety looked especially confusing. I'm sure if I wrote a few of them, it'd come easier.

john02:04:29

But using the built in versions now, like (map inc) look even simpler than their traditional counterparts.

vitruvia03:04:48

;; are meant to be comments in case you are not used to LightTable

noisesmith03:04:39

;; are always comments

vitruvia03:04:24

oh, alright. I was used to the # xD

noisesmith03:04:12

I'm not sure if I'm counting the 0s correctly, but it wants a result larger than the thing it is testing for

noisesmith03:04:33

so equal will not suffice

vitruvia03:04:54

what I understood is that it wants it to be smaller than the thing with many 0s. I had just inserted a condition to return the limited value

noisesmith03:04:08

but that's not larger - it's equal, so it fails

vitruvia03:04:46

I just realized he wanted something smaller and not equal, but it still returns an error if I make it (- 1000000000000000000000000N 1)

vitruvia03:04:31

Yea, still getting used to reading stuff in the proper order in clojure

noisesmith03:04:56

the way I remember is that < and > each want args that go in the direction of the symbol's size

noisesmith03:04:09

< gets larger left to right

noisesmith03:04:30

> gets smaller left to right, just like the symbol itself

noisesmith03:04:39

err, > - got ate

vitruvia03:04:51

thats a nice association to keep in mind

foamdino06:04:35

given this:

foamdino06:04:10

and I have a function that can generate the csv filenames

foamdino06:04:50

how can I generalise the code so that I can generate any number of maps? Should I be thnking about macros here?

not-raspberry10:04:21

macros are almost never the answer when it comes to making a functions more general

not-raspberry10:04:15

But the snippet is not clear enough - what's get-movements and product-id?

not-raspberry13:04:24

@foamdino also what do you mean by any number of maps? Like, more arguments to merge-with?

not-raspberry13:04:46

It already supports any amount of maps:

foamdino14:04:50

^^ solution was apply

foamdino14:04:08

sorry just to give more context:

foamdino14:04:58

I had everything working here apart from I was using a hardcoded set of maps as input to (merge-with +) when I really needed to dynamically the seq of maps based on the input

not-raspberry14:04:42

@foamdino I'm curious, what are the values of the maps? In Clojure + will only sum numbers. In cljs it will also concatenate strings but shouldn't be used that way.

not-raspberry14:04:14

O, I see 'qty' - quantity.

foamdino14:04:25

the values of the maps are {:keyword quantity}

foamdino14:04:39

I got 99% of this code written in a couple of hours, then bashed my head against a brick wall because merge-with wouldn't accept a LazySeq... TIL about apply 😉

dpsutton14:04:27

> merge-with wouldn't accept a LazySeq this sounds wrong

dominicm14:04:18

@dpsutton merge-with works on indexed things, not arbitrary collections, no?

dominicm14:04:47

That's a vector, oops 😆

dpsutton14:04:06

i guess i was thinking it can take an arbitrary number of things to work on and yeah you're right

dominicm14:04:15

works the same with a list though. Treats it as an indexed array.

noisesmith16:04:25

wait, what treats a list as an indexed array?

dominicm17:04:19

Actually, I was using merge-with wrong, ignore me 😆

noisesmith17:04:30

OK, because I was going to say, I can’t think of anything that treats a list as an indexed array in clojure, and merge-with isn’t designed to work with either (though it will happily give you garbage back if you use one of them accidentally)

noisesmith17:04:43

the garbage might even be accidentally correct for your use case…

dominicm17:04:57

^^ There you go, closest to a hack you can do with merge-with 😆. I'm leaving it there.

sakalli18:04:23

busy trying to learn clojure. used to using apply to pass arguments to a function. but don't really follow the logic here. perhaps something silly, but dont understand how it works here. could anybody explain? (encountered the solution in 4clojure):

val_waeselynck18:04:56

@sakalli in this case , (apply map list (partition 2 x))is likes (map list [1 2] [3 4] [5 6])

val_waeselynck18:04:11

that's what apply does

val_waeselynck18:04:06

and you need to understand what map does when given more than one input collection

sakalli18:04:44

aah. now i got it... clear. cheers @val_waeselynck

sakalli18:04:44

step 4 doesnt happen...

val_waeselynck18:04:48

what was the problem statement ?

sakalli18:04:26

my solution was much less elegant than darren's

val_waeselynck18:04:13

yeah you rarely use loop directly in Clojure

sakalli18:04:21

yes. have mostly so far used R, so feel a little dirty each time i resort to loop or for, although like the recur

noisesmith01:04:07

I bring this up a lot, but for is not a loop, it's a list comprehension - it's lazy and not even apropriate for side effects

sakalli04:04:08

yes i know, and it is a bit silly, but still, as esthetically it looks like a for;-)

sakalli04:04:29

even renamed it to listcomp a few times not to have to look at it, haha.