Fork me on GitHub
#beginners
<
2018-01-13
>
Michael Stokley00:01:37

i have a list of vectors i want to use with (map + but i'm getting an ArityException

Michael Stokley00:01:45

because it's a list, i think

Michael Stokley00:01:58

do i need to use apply? or unroll?...

noisesmith00:01:12

neither + or map will give you an ArityException (unless you somehow called map with 0 args)

noisesmith00:01:27

if it's a list of vectors, use (apply map + l)

noisesmith00:01:48

+user=> (apply map + [[1 2 3] [4 5 6]])
(5 7 9)

Michael Stokley00:01:31

that did it, thank you!

jcburley07:01:08

Taking some great offline advice from @scallions, I just refactored some sample code to make it more idiomatic, especially by using the ->> macro (for threading collections). The resulting code is about half the # of lines of the original, much cleaner, easier to read, and makes the difference among different implementations (all in the same file; it's a HackerRank practice-problem solution) much easier to see. I'm definitely falling in love with Clojure! Been heading in this direction, slowly, for decades, including writing my own simple Lisp interpreter...and am grateful to have the time to come up to speed on this new-ish language and (I think) make it the top go-to language in my toolbox, replacing C.

seancorfield07:01:18

Welcome to the Clojure love-fest 🙂

mbjarland13:01:21

@kentoj a bit late to the game but I would have to say from personal experience (having built a fair number of plugins for gradle and run a successful consulting business with large scale production builds exclusively in gradle for the past number of years) that I would under no circumstances move from gradle to maven. Gradle was built in part to address a number of issues with maven. Gradle still has convention, it just doesn't shove it down your throat. Granted, gradle does have a few things which make it a tad tough to get started with (the groovy language and the configuration time vs execution time distinction are among the most common). Anyway, if you have something working with gradle I would think twice before moving that to maven. Only my personal opinion, but a fairly strong one : ) ok...done with my rant of the day.

urbis14:01:35

Hello, I'm trying to implement my own assoc-in function but having troubles, can't understand why it replaces value & doesn't update it

(def numbers [1 2 {:a {:b 4}} 4 5])

(defn my-assoc-in 
  [m [k & ks] v]
  (case (count ks)
    0
    (assoc m k v)
    (assoc m k (my-assoc-in (get k m) ks v))))

(my-assoc-in numbers [2 :b] 4)
returns [1 2 {:b 4} 4 5 instead of [1 2 {:a {:b 4} :b 4} 4 5]

rauh14:01:45

(get k m)? Should be the other way around?

gklijs14:01:17

The problem is that’s its a vector

gklijs14:01:40

(get 2 numbers)
gives nil

noisesmith15:01:30

(get 2 x) for all x is always nil - get is far too accepting of nonsense inputs

noisesmith15:01:51

sometimes (eg. with a vector) (get x 2) will do the right thing

gklijs14:01:46

when run on a vector you want

(nth numbers 2)
to get the old value

urbis14:01:49

@gklijs @rauh Thank you, you are both right 👍

gklijs14:01:57

this

(defn my-assoc-in
  [m [k & ks] v]
  (cond
    (= 0 (count ks)) (assoc m k v)
    (vector? m) (assoc m k (my-assoc-in (nth m k) ks v))
    :else (assoc m k (my-assoc-in (get k m) ks v))))
seems what you want?

urbis14:01:22

@gklijs it's probably strange but

(defn my-assoc-in 
  [m [k & ks] v]
  (case (count ks)
    0
    (assoc m k v)
    (assoc m k (my-assoc-in (get m k) ks v))))
it works like this too

feihong14:01:44

I started a new Clojure web app project that needs to use a couple of web APIs. Where should I put the API keys? Inside profiles.clj?

Prakash14:01:28

profiles.clj work, other idea is to use system env vars or JVM opts

feihong15:01:23

If I put in profiles.clj, what does that look like? I tried putting an API key in :profiles/dev, but was not able to retrieve it using the env function.

feihong15:01:12

Inside the repl, I was unable to use the env function defined in myapp.config to access the API key

Prakash15:01:59

did u use with-profile while running the app/repl?

urbis15:01:55

Hello, is there a better way to do this?

(def a [1 2 3])
(apply + (concat [1 2] a))
For example without concatenation?

rauh15:01:08

How about (as-> (reduce + a) a-sum (reduce + a-sum [1 2))

mbjarland15:01:27

apologies, that was crap : )

feihong15:01:05

Ah, I did not use with-profile when running the repl. I should've asked this first, but does it make sense to put config values that don't change between dev and production in profiles.clj? Would jvm opts or system end vars make more sense in this case?

urbis15:01:33

@rauh basically I'm trying to implement update-in function using update function & struggling with passing arguments in the sane manner, that what I'm currently have

(defn my-update-in
  [m ks f & args]
  (case (count ks)
    1
    (apply
      update
      (concat [m (first ks) f] args))))

Prakash15:01:54

@feihong.hsu all these things are kinda similar, depends on how u will be running the app.

Prakash15:01:38

u can also look at environ for easy access to env/jvm opts

manutter5115:01:29

@feihong.hsu You might want to check out cprop if you haven’t seen it, it’s a nice system for managing config data: https://github.com/tolitius/cprop

Michael Stokley18:01:47

is it possible to implement this stateful algorithm in clojure?

max = my_list[0]
for e in my_list:
    if e > max:
        max = e
print(max)

Michael Stokley18:01:18

i know you could use max, but i'm curious if you could use the imperative style

Prakash18:01:38

should be doable with loop-recur

Michael Stokley18:01:42

maybe with a recursive function that passed the max along?

Alex H18:01:00

reduce, I'd have thought.

Alex H18:01:51

(reduce #(if (> %2 %1) %2 %1) my_list)

Michael Stokley18:01:49

why doesn't the expression (%2 > %1) use prefix notation?

Alex H18:01:06

should, was me being sloppy

Michael Stokley18:01:29

and #(...) is sugar for make function?

Michael Stokley18:01:37

nice, thank you!

Prakash18:01:01

yeah reduce looks like the idiomatic way to do this

Prakash18:01:01

hah, just saw that max is implemented with reduce also - `

Prakash18:01:15

(defn max
  "Returns the greatest of the nums."
  {:added "1.0"
   :inline-arities >1?
   :inline (nary-inline 'max)}
  ([x] x)
  ([x y] (. clojure.lang.Numbers (max x y)))
  ([x y & more]
   (reduce1 max (max x y) more)))

onionpancakes18:01:33

An imperative style would be like this:

(let [my-max (atom (first my-list))]
  (doseq [e my-list]
    (if (> e @my-max)
      (reset! my-max e)))
  @my-max)

Michael Stokley19:01:05

so, i have a list of unit vectors. and my goal is to find the max distance from the origin... for each unit vector, i need to find my current location, which is the sum of all preceding unit vectors

Michael Stokley19:01:51

seems like i need to generate a new list from my list of unit vectors

Michael Stokley19:01:51

something like [0 1 2 3 4 5] --> [0 1 3 6 10 15]

ghadi19:01:20

look at the function reductions

Michael Stokley19:01:24

is there a functional, conventional way to think about this sort of problem?

ghadi19:01:04

what you're doing is taking the starting point sp and moving around, repeatedly -- (if this is off stop me)

nulligor19:01:08

couldn't he just map-indexed into another vector then take the max out of it?

ghadi19:01:33

(move (move (move sp vec1) vec2) vec3) etc

Michael Stokley19:01:55

that's right, yes

ghadi19:01:20

Normally if you use reduce, you'll end up with the ending location. (reduce move starting-point [...bunch of unit vectors])

ghadi19:01:53

But for your use case, you need to find the farthest away one, so you can't just throw away the intermediate positions

ghadi19:01:15

That's what reductions does. It's just a reduce that shows you its work.

ghadi19:01:46

Then you will apply some sort of max (see the max-key function)

ghadi19:01:07

Make sense?

Michael Stokley19:01:08

that makes sense

Michael Stokley19:01:19

thank you for your help!

Michael Stokley19:01:36

is reductions conventional in lisps or functional programming?

ghadi19:01:38

that's a very functional approach, there are other more imperative-y ways to do it, but this is clean

ghadi19:01:54

dunno, reduce is pervasive in functional programming

Chris Bailey19:01:56

Question about using futures (and say same behavior with pmap)… I’m seeing what seems like my program running a minute longer - but after it’s actually done…

Chris Bailey19:01:08

e.g. if I have:

(let [;item1 (some-long-running 1)
      ;item2 (some-long-running 2)
      item1 (future (some-long-running 1))
      item2 (future (some-long-running 2))]
  (time (do (first @item1) (first @item2)))
  (println @item1)
  (println @item2))

ghadi19:01:38

@chris.bailey the thread pools underlying pmap stick around for a minute ^

Chris Bailey19:01:50

I wondered if there was something like that

Chris Bailey19:01:04

bingo, that worked, thank you!

Chris Bailey19:01:31

although seems to raise exception if I do this when the code is run from a test

Chris Bailey19:01:02

tests must be using threads, and now I’ve killed their threadpool

noisesmith19:01:08

right, (shutdown-agents) says you are done with thethread pools

noisesmith19:01:34

I'd say that code that sets up your app or shuts it down should be separate from normal program logic - it needs a different kind of testing

Chris Bailey19:01:37

so if you had a function that computed something, and it could do it’s work in parallel (say with pmap or by using a few futures), how would you test that given this?

ghadi19:01:30

parallel is an execution strategy, ultimately you probably just care that you got the right result

Chris Bailey19:01:42

actually, it seems like the tests, if I don’t use shutdown-agents, finish up fast

ghadi19:01:51

just collect the results of pmap and check em

ghadi19:01:10

tests shouldn't care how you did it (parallel vs. sequential)

Chris Bailey19:01:05

right, agreed - the test is just looking at the results, and that works great. And when run in the tests, the thing runs it’s normal execution time, so it’s only then when I go run it as a program on command line, that it takes a lot longer to return without shutdown-agents.

noisesmith19:01:11

I think the test runner (eg. lein test) will usually do the agent shutdown once it knows all your tests have returned

noisesmith19:01:29

I would expect that at least

Chris Bailey19:01:31

oh, I know what I can do…

Chris Bailey19:01:58

of course - I can run shutdown-agents at the end of my program (vs. this module)

noisesmith19:01:42

yeah - a good pattern is putting testable things into a function, then having a very thin wrapper that does untestable things (or things that shouldn't be tested)

Chris Bailey19:01:56

heh, ya, ok, that was simple

noisesmith19:01:01

and yes, end of your program is the right place for shutdown-agents

Chris Bailey19:01:57

perfect, ok, thank you! I’m pretty darn new to Clojure, but really enjoying it. Been working through some Rosalind (like Euler) problems to help learn, and came across this one that could be sped up by doing stuff in parallel, so was good first try using this stuff.

pny20:01:29

Guys, could someone share some oss clojure projects with component/system strategy and some tests?

seancorfield20:01:08

@pny This will be a good starting point https://crossclj.info/fun/com.stuartsierra.component/Lifecycle.html -- that shows all projects that reference Component's Lifecycle protocol

pny20:01:52

Wow, looks great. Thanks!

pny09:01:18

@U09U89Y6Q many thanks! that's what i'm looking for!