Fork me on GitHub
#beginners
<
2018-12-17
>
madstap10:12:05

@jaihindh.reddy Check out this library that does this for all the java time types https://github.com/magnars/java-time-literals Also, if you print it as #inst and read it back in it'll change type, and lose the offset information.

koala punch11:12:04

hi, i was hoping this snippet would access one key or use another if it is missing

koala punch11:12:19

but the (or) bit doesn’t ever seem to return if the first value is missing

koala punch11:12:54

the second entry always comes out as blank

koala punch11:12:04

i think it’s to do with how i’m accessing the key values inside the map function?

pavlosmelissinos11:12:57

the expression (or :login :id) always returns :login

pavlosmelissinos11:12:43

So your line 10 is equivalent to (map :login users)

pavlosmelissinos11:12:09

You need to turn (or :login :id) into an actual function (e.g. anonymous), so that its outcome is dependent on some input

pavlosmelissinos11:12:06

@christopher.paul do you know how to do that? (hint: you're close)

koala punch11:12:28

sorry was in dm with sundar

koala punch11:12:37

i needed to use some-fn

👍 4
koala punch11:12:48

as the key reference always returns true as it is a function

pavlosmelissinos11:12:33

Oh TIL. That's cleaner than what I had in mind, thanks! For transparency: (map (some-fn :login :id) [{:id "1"}]) -> ("1") vs (map #(or (:login %) (:id %)) [{:id "1"}]) -> ("1")

koala punch11:12:09

i ended up writing my own ropey version of some-fn

koala punch11:12:15

but then found that some-fn existed 🙂

😎 4
Ali Ebadian12:12:42

hey all, I am off work from Wednesday till the new year, do you recon there is a project I can do in that time (because I have 0 life)?

Joseph Hance13:12:08

I have a pattern in Clojure that keeps popping up and I'm not sure the best "clojure-esque" way to do it. Say, for example, I have the following:

user=> (println my-map)
{12 3, 10 4, 8 1, 7 1, 6 1, 4 1}
This is a map of keys (i.e. 12, 10, 8, …) with associated values (3, 4, 1, …) I'm interested in finding the INDEX of the item in the map with the max value. So in this case [10 4] is the one I'm interested in and I want its index which is 1.

bronsa13:12:59

maps are unordered

bronsa13:12:06

an "index" for a map makes no sense

Alex Miller (Clojure team)13:12:21

well it does… from a key to a value :)

bronsa13:12:35

well yes, I meant not an "index" in the sense he's talking about

😝 4
bronsa13:12:43

an ordered index :)

danielneal13:12:14

You can use https://github.com/clj-commons/ordered if you want ordered maps though

4
Joseph Hance13:12:22

Ok, then how do I get it "ordered" so that I can get the one I'm interested in?

Alex Miller (Clojure team)13:12:53

well, you might also consider sorted-maps, not sure if they would satisfy

danielneal13:12:26

What specifically do you want the order for?

bronsa14:12:56

FWIW @joseph.hance if you're actually using maps as if they were ordered, it's not just a conceptual issue, the insertion order actually does get shuffled around randomly

user=> {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9}
{7 7, 1 1, 4 4, 6 6, 3 3, 2 2, 9 9, 5 5, 8 8}

pavlosmelissinos14:12:15

Are you sure the shuffling is random? I'm getting the exact same result as you

bronsa14:12:09

it's not "random", it's just not guaranteed

bronsa14:12:16

the order is dependent on the hashing function

bronsa14:12:32

the hashing function that my repl is the same that your uses so the results are consistent

pavlosmelissinos14:12:52

But it's still unpredictable in practice

bronsa14:12:53

but, for all practical purposes, you can consider it as being random

bronsa14:12:14

esp as the hashing can produce different results depending on JVM version

bronsa14:12:28

and the ordering can change based on collision order etc

pavlosmelissinos14:12:14

Got it, thanks 😉

Joseph Hance14:12:11

Let me take a step back, I have:

user=> (println my-map)
{12 3, 10 4, 8 1, 7 1, 6 1, 4 1}
And I want to find [10 4] because 4 is the max value in this data structure.

bronsa14:12:25

right, then you don't need an index at all

Joseph Hance14:12:43

Note: beginner talking here.

manutter5114:12:20

What if you just take “10” as the “index” you want? Will that meet your needs?

bronsa14:12:44

user=> (apply max-key val {12 3, 10 4, 8 1, 7 1, 6 1, 4 1})
[10 4]

bronsa14:12:23

let me know if you need help understanding why that works

manutter5114:12:45

lol, this is the first I’ve heard that there was a max-key fn in clojure core.

bronsa14:12:16

it annoys me a lot that it works on varargs rather than on a single sequence :)

manutter5114:12:58

Yeah I can see where that would be annoying.

bronsa14:12:40

it's the way it is because it's an "enhanced" max, but it feels closer to a filter-like function to me

manutter5114:12:12

@joseph.hance can you give a bigger-picture example of a case where you run into this pattern? I have a feeling we may be missing the forest for the trees and it sounds like you may have an interesting question behind your question.

Joseph Hance14:12:49

...looking up max-key. Thanks.

Ian Fernandez14:12:14

how can I do something like this:

(rename-keys (function-gives-map arg1) {:key1 :keey})
to a thread macro like this:
(-> arg1 function-gives-map ...)

bronsa14:12:13

(-> arg1 function-gives-map (rename-keys {:key1 :keey}))

bronsa14:12:37

user=> (macroexpand-1 '(-> arg1 function-gives-map (rename-keys {:key1 :keey})))
(rename-keys (function-gives-map arg1) {:key1 :keey})

Ian Fernandez14:12:52

there's no problem with arity ordering?

bronsa14:12:08

-> will always insert the piped argument as the first argument to the function

bronsa14:12:12

->> as the last

Ian Fernandez14:12:56

yeah, but rename-keys takes map and another map of keys that I rename]

Ian Fernandez14:12:31

if I wanted to put in the second arg of rename-keys I would use ->> ?

bronsa14:12:44

if you (-> arg1 (f arg2)) you'll get (f arg1 arg2)

bronsa14:12:10

(->> argN (f arg1 arg2)) will give you (f arg1 arg2 argN)

bronsa14:12:44

play with macroexpand-1 as I've shown above to get a feel if you're not sure what a macro does

potetm15:12:28

Hey! People who are learning clojure and doing Advent of Code! Last week I did a code review on stream, and I found it to be a fun and interesting exercise. https://www.twitch.tv/videos/349004355?t=55m30s If anyone wants me to do the same for their Advent of Code code, please let me know! I won’t do one every day (and I won’t do one today), but I’d like to do one a couple times a week if enough submissions roll in.

felipebarros20:12:28

It was awesome, thank you so much for the initiative. Unfortunately I couldn't attend as I expected, but I believe workflow sharing (so that others can understand REPL usage, interesting tools and dynamics) is the best approach forward if we want people to understand the niceties of the language and how the parentheses disappear. 🙂 Thanks!

truestory 4
potetm22:12:55

My pleasure! And I totally agree. Hope you find the stream helpful 🙂

anonfish16:12:12

Is there a better way to write this utility function?

(defn read-int-from-envvar-with-fallback [env_var_name default_val]
	(min
		(try
			(. Integer parseInt (System/getenv env_var_name))
			(catch Exception e default_val))
		default_val))

valerauko16:12:41

why the min?

anonfish16:12:02

Values more than default-value are invalid

val_waeselynck16:12:04

(if-some [txt (System/getenv env_var_name)]
  (min 
    (Long/parseLong env_var_name 10) ;; NOTE you should pass the radix explicitly
    default-val)
  default-val)
@nilesh.tr

jstaab17:12:21

Is there a version of assoc that only sets the key if it's empty?

andy.fingerhut17:12:08

Maybe something like this? (merge my-map {:add-key-if-new 7, :another-key-but-only-if-new 23})

jaihindhreddy-duplicate17:12:51

merge will overwrite existing keys right?

andy.fingerhut17:12:57

oh, but probably the other way around on the args there. sorry

andy.fingerhut17:12:20

and that isn't necessarily the fastest way to achieve what you asked, for a single key.

jstaab17:12:48

Maybe (defn assoc-default [m k v] (if (get m k) m (assoc m k v)))

jstaab17:12:57

Just curious if there was something in the standard library

andy.fingerhut17:12:08

I can't think of anything off hand that is already there, like that.

jstaab17:12:13

Ok, thanks

enforser18:12:30

@jstaab maybe update? (update m k #(or % v)) Also, these functions will not work if nil or false are valid values in the map. You could support those by changing from (get m k) to (contains? m k)

👍 4
hiredman18:12:06

(update-in m [k] (fnil identity v))

💯 12
jstaab18:12:50

I'll probably use the merge version in most places, but that's pretty elegant

bpenguin19:12:15

Hey guys, I'm wondering if you can help me out. I am trying to play around with luminus and get that running. I can create a new app from template lein new luminus firsttest +postgres and I have a postgres url string set as the :database-url "" I can start the app and run the default user migrations, but

user=> (firsttest.db.core/create-user! { :id "fun1" :first_name "me" :last_name "me" :pass "secret" :email "" })

IllegalArgumentException db-spec mount.core.DerefableState@548f4400 is missing a required parameter  clojure.java.jdbc/get-connection (jdbc.clj:409)
Any idea where I could start digging in to where this error is coming from? PS -> the project clj file https://gist.github.com/brimatteng/f8925474224c5c8b2a3badac7af1955d

eggsyntax00:12:27

Hey @U9CPW8J1Y, did you figure this out? I can take a look, but I want to check that you haven’t figured it out already 🙂

eggsyntax00:12:28

(PM me if I don’t reply soon, I may not see notification)

bpenguin02:12:27

Hey I haven’t gotten much further than this. It might be a problem with the luminous template for Postgres

jaide02:12:04

@U9CPW8J1Y Can you paste your queries.sql please?

eggsyntax02:12:20

@U9CPW8J1Y and what do you get if you run lein test from the root dir?

eggsyntax02:12:52

@U8WFYMFRU here’s the queries.sql created by that template:

eggsyntax02:12:02

-- :name create-user! :! :n
-- :doc creates a new user record
INSERT INTO users
(id, first_name, last_name, email, pass)
VALUES (:id, :first_name, :last_name, :email, :pass)

-- :name update-user! :! :n
-- :doc updates an existing user record
UPDATE users
SET first_name = :first_name, last_name = :last_name, email = :email
WHERE id = :id

-- :name get-user :? :1
-- :doc retrieves a user record given the id
SELECT * FROM users
WHERE id = :id

-- :name delete-user! :! :n
-- :doc deletes a user record given the id
DELETE FROM users
WHERE id = :id

eggsyntax02:12:20

@U9CPW8J1Y I may be too rusty on postgres to help with this one. Thanks @U8WFYMFRU!

jaide02:12:10

I did just launch a postgres luminus app a couple of weeks ago so it’s a bit more fresh.

jaide02:12:55

@U9CPW8J1Y The queries looks good, what about the test file?

jaide02:12:22

In my test, db was accessed differently:

(ns firsttest.test.db.core
  (:require [firsttest.db.core :refer [*db*] :as db]

jaide02:12:37

And queries required the connection as the first param

jaide02:12:12

(ns firsttest.test.db.core
  (:require [firsttest.db.core :refer [*db*] :as db]
            [luminus-migrations.core :as migrations]
            [clojure.test :refer :all]
            [clojure.java.jdbc :as jdbc]
            [firsttest.config :refer [env]]
            [mount.core :as mount]))

(use-fixtures
  :once
  (fn [f]
    (mount/start
      #'firsttest.config/env
      #'firsttest.db.core/*db*)
    (migrations/migrate ["migrate"] (select-keys env [:database-url]))
    (f)))

(deftest test-save-user
  (testing "Save user to db"
    (jdbc/with-db-transaction [t-conn *db*]
      (jdbc/db-set-rollback-only! t-conn)
      (is (db/create-user! t-conn
                           {:id "fun1"
                            :first_name "me"
                            :last_name "me"
                            :pass "secret"
                            :email ""})))))