Fork me on GitHub
#beginners
<
2018-12-01
>
_rj_r_02:12:08

So question.. when you wrap the request as shown here, how does the database handle the open/closing of the connection? Is the connection always open? This is a postgresql database, so it might be my lack of postgresql knowledge, but I was curious what happens to the connection for each user connecting and disconnecting.

hiredman03:12:40

I dunno where you are getting that code from, but I wouldn't be surprised if they assume a connection pool

hiredman03:12:24

but a lot depends on the value of db, and even what kind of db it is, what library you are using to talk to it

hiredman03:12:45

that code tells you almost nothing about it

_rj_r_13:12:00

So I already stated that it was a Postgres database. The value of db is:

(def db (or
         (System/getenv "DATABASE_URL")
         "jdbc:))
The libraries used are:
[org.postgresql/postgresql "42.2.5"]
[org.clojure/java.jdbc "0.7.8"]
The code came from an Eric Normand video. For future reference, just simply ask for the additional information needed. Obviously if I knew all the information needed for any one of the many people in here to assist, I would have posted it. Thanks.

noisesmith16:12:43

with-open closes the object you open when execution leaves that block

noisesmith17:12:14

the point about connection pools is that the right place to manage reuse of connection objects is via some connection pool, not by replacing the usage of with-open (which in the case of a connection pool will close a connection-pool view of a connection but let the pool decide how many connections to keep open and how to use them)

Daouda07:12:22

hey folks, can you tell me if a set can be transformed in vector? if yes, one to achieve it?

Daouda07:12:06

i tried with into but does not work

schmee07:12:25

@quieterkali sure!

user=> (vec #{1 2 3})
[1 3 2]

schmee07:12:54

(into [] #{1 2 3}) also works

Daouda07:12:39

thank you very much @schmee 🙂

Adb09:12:27

I'm testing out clojure in the repl for the first time

schmee09:12:50

that’s strange, works for me:

user=> (require '[clojure.string :as str])
nil
user=> (str/starts-with? "abc" "a")
true

schmee09:12:56

maybe try restarting your REPL?

Adb09:12:56

Thanks alot, just needed to know that it's not a problem with my 'code'😄

andy.fingerhut10:12:21

What operating system are you using, and what method are you using to start your REPL?

Adb10:12:25

Windows and light tables insta repl

andy.fingerhut11:12:15

I'm not the best advisor on using Clojure on Windows, but I will mention that light table has not been updated in a while, and might lead to some rough edges that won't be addressed any time soon (if ever).

andy.fingerhut11:12:15

If you have Windows 10 with WSL, I have heard that can in some cases provide a more Linux-like experience, where Clojure environments tend to be a more tested and polished than on Windows.

Adb09:12:45

but this gives me java.lang.RuntimeException: No such var: str/starts-with?

SoV414:12:15

I asked a question on stack overflow about rendering comment-trees. maybe if you have a second, take a look, I'd appreciate any help on the topiic ^_^ https://stackoverflow.com/questions/53571904/render-comment-tree-with-rum

johnj15:12:47

@sova recur back to where?

johnj15:12:36

normally the lost of knowledge is handled with accumulators

SoV415:12:21

it's a datastructure just one level deep, but some entries might require the addition of further entries...

SoV415:12:53

{:content "hax" :id 33 :comments [34 35} would pull out 33, 34, and 35, and potentially any comments 34 and 35 have...

SoV415:12:04

accumulators... googles eagerly

Daouda15:12:31

hey guys, can i go over set element using reduce? how, please?

SoV415:12:38

@quieterkali 'set element" ?

Daouda15:12:20

set values i meant&34547*

Daouda15:12:30

set values*

Daouda15:12:28

i wanted to use reduce to go through each set values, and perform some oparation and store the result as accumulate avector

SoV415:12:25

I don't know what set values is for, it sounds feasible

Daouda15:12:05

ok let's forget about the set

Daouda15:12:27

let's say i have a vector [1 2 3 4 5]

Daouda15:12:30

iterate through it, using reduce to perform some computing

SoV415:12:02

sure, maybe you do reduce-kv

potetm15:12:05

@quieterkali Maybe just tell what you’re trying to do?

potetm15:12:20

(reduce + 0 [1 2 3 4 5])

potetm15:12:33

does what you’re saying, but I’m not sure whether that’s helpful to you

Daouda15:12:59

want to come up with best way to go over a vector where i will pass each value to a function which will return me another vector, the i will just use conj add the vector to the reduce accumulator

Daouda15:12:51

if i am not clear enough let me know please

SoV415:12:19

sounds like a neural net o.O

Daouda15:12:28

(reduce fn [] [1 2 3 4 5])

SoV415:12:54

when you say "`conj` add the vector to the reduce accumulator" do you mean the original reduce fxn's accumulator?

Daouda15:12:08

yeah exactly

SoV415:12:09

you could have a global atom store the accumulator state, and then toy with it from separate functions

potetm15:12:57

@quieterkali it sounds like you want mapcat

Daouda15:12:59

i want to use recuce exactly to not have to use an atom

potetm15:12:48

(mapcat :vals [{:vals [1 2 3]}
               {:vals [4 5 6]}])

potetm15:12:56

=> (1 2 3 4 5 6)

potetm15:12:43

Does that look like it’s going in the right direction?

Daouda15:12:29

the problem is that i don't have those vals yet

Daouda15:12:00

i just have a vector which i'll use to get those vals

potetm15:12:30

You can use any function to replace :vals!

potetm15:12:42

(mapcat (fn [i]
          (range i))
        (range 10))
=> (0 0 1 0 1 2 0 1 2 3 0 1 2 3 4 0 1 2 3 4 5 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8)

Daouda15:12:06

so take the vector, go through each values of it, retrieve the corresponding vector, then can use mapcat to concat

Daouda15:12:39

that is what i want to acheive

Daouda15:12:08

the ideia is collect the list of friends of my friends

Daouda15:12:40

and join into a big list that i will use for other computing

potetm15:12:22

ah yeah, I think mapcat is your friend here

Daouda15:12:28

@potetm, @sova thank you very much for your help 🙂

Azzurite17:12:50

is there anyway to find out from code if the code itself is being ran with a specific leiningen profile? the only thing I came up with is to conditionally include a certain source directory, which can add namespaces which you can check for

pvillegas1218:12:07

I have

public abstract class KeyStoreKeyingDataProvider implements KeyingDataProvider
{
    /**
     * Provides a password to load the keystore.
     */
    public interface KeyStorePasswordProvider
    {
        char[] getPassword();
    }
How do I access KeyStorePasswordProvider from clojure? Trying to extend this with proxy I tried KeyStoreKeyingDataProvider/KeyStorePasswordProvider but it does not find the class

Daouda18:12:53

hey guys 🙂 , let's say i have 2 vectors [1 2 4 3 2 5 5 1] and [1 3 4] and want this output [2 2 5 5]

Daouda18:12:39

basically take all occurence of one from another. clojure function to achieve that?

NoahTheDuke18:12:14

off the top of my head, without checking: (remove #(some (fn [x] (= x %)) [1 3 4]) [1 2 4 3 2 5 5 1])

NoahTheDuke18:12:52

for each element in longer-list, if it exists in smaller-list, remove it, otherwise continue

potetm18:12:13

depending on list size, that’s^ can get crazy inefficient

NoahTheDuke18:12:19

oh yeah, it's not good lol

Chris18:12:56

Sets to the rescue...

potetm18:12:05

sets wont work

potetm18:12:07

it has dups

Daouda18:12:16

Set will remove all duplication, which i don't want

Chris18:12:16

The second list can be a set

Chris18:12:24

The one you are looking up

Chris18:12:33

The first list remains a vector

Daouda18:12:34

@potetm exactly 🙂

potetm18:12:38

(remove (set [1 3 4]) [1 2 4 ...])

potetm18:12:47

@cbowdon exactly

Daouda18:12:45

oh yeah that did the trick guys

Daouda18:12:39

@potetm @nbtheduke @cbowdon thank you very very very much guys

SoV419:12:08

computational science is mostly sequential math over collections

Daouda19:12:44

fair enough @sova

Daouda19:12:27

hey guys, it me again, need you to take a lokk to this and tell if there is a better way to acheive the same thing

Daouda19:12:26

took it from clojure sorted-map-by documentation

Daouda19:12:53

it give follwing output: {5 2, 2 2, 4 1, 3 1}

potetm19:12:11

depends on what you need

Daouda19:12:07

i need it to return the map ordered by the values

Daouda19:12:12

not by the keys

Daouda19:12:51

so i give this {2 2, 4 1, 3 1, 5 2} and give me back {5 2, 2 2, 4 1, 3 1}

potetm19:12:50

(sort-by val
           >
           results)

potetm19:12:15

=> ([2 2] [5 2] [4 1] [3 1])

potetm19:12:46

so it’s a different return type, but what you’re asserting is that you need indexed access as well

potetm19:12:55

(which you already have via your results map)

potetm19:12:17

(sort-by (fn [[k v]]
             [v k])
           (fn [a b]
             (compare b a))
           results)
matches your sort order exactly

Daouda19:12:18

looks like this is even better

Daouda19:12:01

let me check it please

Daouda19:12:14

did the trick 🙂

Daouda19:12:13

i did a small update to make it look the way i want kkkkkkkk

Daouda19:12:33

thank you @potetm

potetm19:12:48

that won’t do what you want!

potetm19:12:56

it happens to be sorted

Daouda19:12:58

kkkkkkkkkkkkkkkk

potetm20:12:00

because your list is small

potetm20:12:06

put more than 10 items in your list

Daouda20:12:09

hahahahahahahahaha

potetm20:12:11

and it will get un-sorted

potetm20:12:23

the semantics of {} are just k->v

Daouda20:12:41

so what should i do now?

Daouda20:12:52

use sorted-map a guess

potetm20:12:55

curious why you need a sorted hashmap as opposed to a hasmap + sorted list of key-values

potetm20:12:13

if that’s really what you need, your original solution is the way to do it

Daouda20:12:19

i used frequencies on a vector and i got a map

Daouda20:12:35

i need to ordered the map now by the values

Daouda20:12:04

and then thank each one in order to look for the corresponding user

dpsutton20:12:11

Why do you need them ordered? What context do you intend to use them

Daouda20:12:18

list of friend suggestion

dpsutton20:12:09

It seems like at point you don't need it to be a map. You just need to interate through the key value pairs in a sorted order

Daouda20:12:11

i am working on friend list suggestion

potetm20:12:34

right so:

(map (fn [[user-id count]]
       (thank-user user-id))
     (sort-by val
              >
              results))

potetm20:12:17

(Maybe better in a doseq. I try to not do side-effects inside a mapping operation.)

potetm20:12:47

so:

(doseq [[user-id count] (sort-by val
                                 >
                                 results)]
  (thank-user user-id))

Daouda00:12:38

i am facing a problem with this snippet code. What is it suppose to give me back after finish running? A vector?

potetm01:12:06

doseq returns nil

potetm01:12:15

It just does things for side-effect

potetm01:12:04

If you need to build up a result, I would use loop/recur, an atom in a doseq, or doall

Daouda20:12:11

checking with my problem...

Daouda20:12:41

@potetm what thank-user means?

potetm20:12:36

I wasn’t sure what you meant, so I just stuck that in there as a placeholder for whatever you want to do w/ each user

Daouda20:12:46

oh i see, it could be the function i will call to get the user

SoV420:12:04

I am so happy, I figured out how to nest comments like I was wondering earlier/forever.

Daouda20:12:31

show us how please hahahahaha

SoV420:12:04

Sure thing 😄

Daouda20:12:19

@potetm @dpsutton @sova thanks for your help 🙂

SoV420:12:38

rum render of data. top half is "no comments for this entry, so print a dead-ended output of its contents, author" bottom half is: there are comments, print the relevant fields and when it gets to "comments" map the render-item function back over the cids you got [in that frame]

SoV420:12:00

example rendering of output in html

SoV420:12:22

my CSS for .padleft is also relevant: it's very brief

SoV420:12:45

indent yo comment tree

SoV420:12:10

So yeah! those 4 images can make a pro comment-tree maker out of anybody ^_^

potetm20:12:11

So something to consider: it’s doing a linear scan for each render-item(filter ... posts)

potetm20:12:04

You can eliminate that if you store your posts like so:

{77 {:id 77, :contents "" ... }
 33 {:id 33, :contents "" ...}}

potetm20:12:20

so that’ll give you a direct lookup

SoV420:12:21

Neat. hmm

SoV420:12:32

post-id {post-map}

SoV420:12:51

Okay, and how would I alter my code to shortcut that lookup instead of using filter

potetm20:12:50

(get @posts pid) for every filter

SoV420:12:18

But not (:pid @posts)

SoV420:12:55

okay, that's a subtle distinction where you can use (get ..) and the inverted syntaqs don't werk

SoV420:12:33

because (pid @posts) would kinda be absurd..

potetm20:12:38

(:pid posts) means you have a map of {:pid {:post “”}}

potetm20:12:58

(pid posts) means pid is a function

SoV420:12:03

Haha! right!

potetm20:12:04

and number aren’t functions in clojure

SoV420:12:15

i'll seven your web app to death

potetm20:12:47

Also: this doesn’t matter so much in cljs, but

potetm20:12:53

when using atoms

potetm20:12:12

you kind of want to start out by saying:

(let [posts @posts] ....)

potetm20:12:20

that way you have the same value of post for the entire function

SoV420:12:27

Ah. and not to dereference multiple times.

potetm20:12:31

or, perhaps even pass in posts

potetm20:12:35

so the function becomes pure

potetm20:12:46

right, it’s a race condition if you do multiple reads

SoV420:12:47

no mud no lotus

potetm20:12:16

cljs is single-threaded and doesn’t interrupt control flow

potetm20:12:27

so it’s not actually an issue for you

potetm20:12:43

but if you went to clojure w/ that, you would have a bad time

SoV420:12:46

Interesting

SoV420:12:55

thank you very much for pointing that out & other points

potetm20:12:23

Here’s a bonus function for indexing by id:

(defn idx-by-id [id-key coll]
  (into {}
        (map (fn [{id id-key :as item}]
               [id item]))
        coll))

SoV420:12:00

so that will make a map that looks like {"77" {:itemzzz...}} ?

potetm20:12:20

call it like (idx-by-id :pid posts)

SoV420:12:36

wow that was painless

SoV420:12:40

in my case :id and @posts

Daouda20:12:54

@potetm you prefrered doseq over map, can you please tell me why?

potetm20:12:27

sequence fns in clojure imply that execution can be lazy

potetm20:12:38

so map, filter, et al

potetm20:12:59

when you have side-effects, you usually want to control when you do the side effect

Daouda20:12:22

meaning please, see this word a lot, but what it imply i really do't know for sure

potetm20:12:35

(do (range)
    :foo)

potetm20:12:38

run that in a repl

potetm20:12:19

returns :foo immediately?

SoV420:12:26

lazy eval: i only grow coffee beans when i want to drink coffee

potetm20:12:30

Now just run (range)

potetm20:12:56

(feel free to cancel execution at any time 🙂)

Daouda20:12:59

oooooooooooooooooooooooow

Daouda20:12:17

my computer start looking like matrix

Daouda20:12:19

kkkkkkkkkkk

potetm20:12:28

what happened is your repl was trying to print the output of (range)

potetm20:12:50

which is infinite

SoV420:12:52

why isn't (matrix) in clojure.core

potetm20:12:01

but the first one, you didn’t use (range) at all

potetm20:12:20

so it didn’t do anything

potetm20:12:47

now when you say (map inc [1 2 3])

potetm20:12:50

the same thing applies

Daouda20:12:57

so in the first one range is thet but i didnt use it at all

potetm20:12:39

yes, exactly

potetm20:12:47

it creates a sequence, but nothing happens with it

potetm20:12:00

now if you do

(do (map (fn [i]
           (println i)
           (inc i))
         [1 2 3])
    :foo)

potetm20:12:17

nothing gets printed, right?

potetm20:12:32

whereas:

(map (fn [i]
       (println i)
       (inc i))
     [1 2 3])

potetm20:12:35

prints things

Daouda20:12:59

yeah print

Daouda20:12:10

only map, print

potetm20:12:13

so that’s an example of a side effect inside a sequence operation

potetm20:12:40

it probably doesn’t do quite what you want

potetm20:12:17

maybe a better example:

(let [myseq (map (fn [i]
                   (println i)
                   (inc i))
                 [1 2 3])]
  (println "foo"))

potetm20:12:34

it looks like it would print “1 2 3 foo”

potetm20:12:57

but it doesn’t

Daouda20:12:24

only foo nil

potetm20:12:36

(doseq [i (map (fn [i]
                 (inc i))
               [1 2 3])]
  (println i))
(println "foo")

potetm20:12:46

but that does exactly what it looks like it does

potetm20:12:57

because doseq is “eager”

potetm20:12:07

it executes everything immediately

potetm20:12:41

so, it’s possible to do side effects in sequence operations

potetm20:12:46

and sometimes it works fine

potetm20:12:59

but it’s unnecessarily confusing imo

potetm20:12:05

in terms of what gets executed when

potetm20:12:21

because sequence fns mean “I don’t care when you do this. Just do it whenever.”

potetm20:12:57

and w/ side effects (e.g. looking up users in a db), you generally want to control when that happens

potetm20:12:13

“ok, now that we have all the ids, go get the users in a single call”

Daouda20:12:48

it's really interesting

Daouda20:12:14

can you provide me some links to dig deep on it

Daouda20:12:34

i think i got it, but i would like to make sure of that

Daouda20:12:47

and i will come bak to you with more quesstion hehehehehe

Daouda20:12:24

@potetm thank you very muuuch 🙂

potetm20:12:34

@quieterkali and @sova Since it seems like ya’ll are trying to skill up on clojure, I’d like to mention my stream I started last week: https://www.twitch.tv/timpote

potetm20:12:54

Gonna be doing Advent of Code, but geared toward clojure beginner/intermediates

potetm20:12:03

would love to hear your questions there!

Daouda20:12:26

@potetm signing up there hehehehe

potetm20:12:22

M-F @ 12:00 CST

potetm20:12:43

I suppose it would be useful if I mentioned that on Monday I’m planning to cover a lot of clojure topics: imperative vs functional, loop/recur, reduce, transducers

potetm20:12:59

oughta be pretty good 🙂

Daouda21:12:29

so on Mondays and Fridays ?

potetm21:12:50

Monday thru Friday

potetm21:12:54

every weekday

Daouda21:12:09

ooooooooooooowwwwwwwwwwww

Daouda21:12:25

i got it now

Daouda21:12:41

setting up my google agenda to not miss them hahahaha

Daouda21:12:09

duration 1h, right?

potetm21:12:50

yeah between 30min and 1 hr

potetm21:12:57

Monday will probably be a full hour

Karol Wójcik21:12:05

What is an idiomatic way of waiting for multiple chans to finish?

Karol Wójcik21:12:05

What is an idiomatic way of waiting for multiple chans to finish?

Ben Grabow21:12:40

Do you want only the first result back, or do you want the result of all chans?

Karol Wójcik21:12:58

I want the result of all chans

Karol Wójcik21:12:50

I’m looking for something like Promise.all in Javascript

Azzurite21:12:55

a channel is not even close to a Promise in Javascript, are you sure you don't want a future instead? channels aren't really things where you get "a result" from, as they're supposed to be continously running

Ben Grabow21:12:39

Do you need exactly one (or balanced) results from all channels, or is it okay to be unbalanced?

Azzurite21:12:44

but yeah, to get one item from each channel you can simply do (map <! channels) where channels is your list of channels

Karol Wójcik21:12:33

Here is a snippet:

(defn call!
  [db configuration]
  (let [chans (map (fn [_] (async/thread (seed-db! db configuration)))
                   (range 0 (:times configuration)))]
    (async/<!! (async/merge chans))
    (println "All threads execution finished" chans)))

Karol Wójcik21:12:54

What I want to achieve is to wait for all threads to finish

Karol Wójcik21:12:33

I don’t care what is a result of execution since it only seeds the DB

Ben Grabow22:12:17

So from a more abstract perspective, you have n tasks to complete asynchronously, and you want to know when they are all done. Right?

Karol Wójcik22:12:19

Exactly @UANMXF34G

Ben Grabow22:12:01

pmap might be a good approach that doesn't require core.async at all. https://clojuredocs.org/clojure.core/pmap#example-542692cdc026201cdc326cf4

Azzurite22:12:40

you don't need pmap if you want to wait anyway

Azzurite22:12:56

and if you don't need the results you don't need map either

Azzurite22:12:21

you can (doseq [c chans] (<!! c))

Azzurite22:12:56

pmap and map are lazy, so if you really want to use map you have to do (doall (map <!! chans))

Ben Grabow22:12:59

(doall (pmap seed-db! db-configurations) gives you the parallelism without using channels at all, as an alternative approach. If you also want to return immediately and check the result later you can wrap it in future to get the asynchronicity. Something about channels seems to imply that values need to be conveyed around, which isn't what's happening in this case so it doesn't seem quite right. Either will work just fine of course.

Azzurite22:12:49

that's much smarter 😄

Azzurite22:12:57

but I think I still prefer the doseq approach, as using map for side effects is discouraged

Ben Grabow00:12:04

This is a funny case where the synchronous version doesn't return anything, but the asynchronous version kind of does in a way? The async version needs to return some signal that indicates the tasks are done, whether that's a promise, or nil on a channel, or a collection of nils for each of the tasks. Synchronous code always has an implicit "I'm done doing the thing you said to do" signal in the form of the function returning execution control to the calling context. When a task is called asynchronously, this signal needs to be reified in some form.

Ben Grabow00:12:31

For a single async task, the idiomatic thing is probably (future some-task). For the parallel collection version, I'm leaning towards

(let [futures (doall (map #(future some-task) task-configs))]
  (doseq [fut futures] (deref fut)))
This doesn't feel terribly idiomatic, maybe because performing a bunch of side effects and returning nil is not very idiomatic Clojure. 😉

Karol Wójcik10:12:16

Nice guys! Thank you all 🙂