Fork me on GitHub
#beginners
<
2018-05-30
>
aj07mm00:05:04

It's common to define it in a separated file called entities.clj? And that is the common way to address the handling of database records or there is some different pattern in the functional programming context?

akiroz00:05:44

There's no definition for a map, if you query SELECT foo, bar, qux FROM baz you'd get a list of {:foo 1 :bar 2 :qux 3}

akiroz00:05:31

Actually there's no such concept as a "database record", it's just plain data and there's no DB logic coupled to it

seancorfield00:05:05

@aj07mm If you're using org.clojure/java.jdbc, you'd just do something like

(jdbc/query db-spec ["SELECT * FROM mytable WHERE somecol < ?" threshold])
and you'll get back a sequence of hash maps. No definitions necessary.

seancorfield00:05:56

Have a look at the community managed documentation for java.jdbc http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html

seancorfield00:05:21

(and if you're doing database-driven stuff and get into difficulty, pop into #sql and ask questions -- I'm guaranteed to see them there and I'm the maintainer of the Clojure Contrib wrapper for JDBC)

seancorfield00:05:19

Welcome to the world of data @aj07mm! šŸ™‚

aj07mm00:05:39

hehehe nice, thanks so much guys!

ScArcher04:05:39

Can someone help me add 3600 seconds to a date time in clojure?

ScArcher04:05:17

wow, thanks @chad I should have caught that šŸ™‚

šŸ‘ 4
seancorfield06:05:03

@scott.archer If you're on Java 8 or later, you should consider using Java Time, either directly or via something like clojure.java-time.

šŸ‘ 4
seancorfield06:05:20

The maintainers of Joda Time want folks to migrate away from it (to Java Time).

seancorfield06:05:38

(which is why I added that notice to clj-time's README recently)

seancorfield06:05:43

sean@sean-xps:~/clojure$ clj -Sdeps '{:deps {clojure.java-time {:mvn/version "RELEASE"}}}'
Clojure 1.9.0
user=> (require '[java-time :as jt])
nil
user=> (jt/plus (jt/instant) (jt/seconds 3600))
#object[java.time.Instant 0x1c3259fa "2018-05-30T07:04:15.504Z"]
user=> (jt/java-date *1)
#inst "2018-05-30T07:04:15.504-00:00"
user=> (jt/instant)
#object[java.time.Instant 0x2954f6ab "2018-05-30T06:04:49.947Z"]
user=>
(The clojure.java-time equivalent of what you did with clj-time above)

lepistane10:05:48

i went through this http://elbenshira.com/blog/understanding-transducers/ and i can do these examples using (map ... (map ... )) and the only thing from blog (i think it was mentioned in blog) is to not have those seq in between but if they are lazy what's the point? what is the use case for transducers?

schmee10:05:00

one point is that they can be reused in different contexts, for example for seqs and core async channels

schmee10:05:32

another point is that since they donā€™t materialize intermediate results they allocate less which reduces garbage collection pressure

shakdwipeea10:05:37

Is pomegranate supposed to work in a jar ? It works from the repl but from jar I get Could not find a suitable classloader to modify from clojure.lang.LazySeq@385266a9

eggsyntax12:05:27

"Is pomegranate supposed to work in a jar?" Best question I've seen in ages for confusing non-programmers šŸ˜‰

šŸ˜‚ 4
eggsyntax12:05:42

(unfortunately I don't know the answer)

shakdwipeea13:05:28

Also in the Readme https://github.com/cemerick/pomegranate/#urlclassloader-modifiability > you will need to explicitly enable the java.net.URLClassLoader support in dynapath (upon which pomegranate relies for such things). but I couldn't find anything on how to enable this support.

fabrao14:05:01

Hello all, I have a map {:value1 1 :value2 2 :value3 3}. Is there any easy way to convert it to array-map?

fabrao14:05:38

:thinking_face:

dpsutton14:05:45

Just for curiosity @fabrao what do you need to achieve?

fabrao14:05:03

@dpsutton I need {:value1 1 :value2 2 :value3 3} to be in original order

bronsa14:05:09

@alexmiller into wonā€™t work here, if |m| > PHM.threshold

bronsa14:05:27

@fabrao if youā€™ve already lost ordering thereā€™s no way to get it back

fabrao14:05:29

but when I create it, the order mess up

dpsutton14:05:52

Because you're cementing the already "scrambled" order

bronsa14:05:54

you need to make an explicit array-map beforehand

bronsa14:05:12

but the gotcha is that as soon as you conj or disj onto it, it might lose ordering

fabrao14:05:28

like (array-map :value1 1 :value 2 ...) ?

bronsa14:05:33

so I would reccomend using a different data structure unless youā€™re ok with your array-map being read-only

fabrao14:05:04

yes, array-map is just read only

fabrao14:05:31

*I can handle with read-only

dpsutton14:05:05

Do you need random access into something you're explicitly ordering? Maybe just a vector of stuff is very

Alex Miller (Clojure team)14:05:30

Iā€™d agree with structuring your data different as the first choice. https://github.com/amalloy/ordered is pretty useful too.

fabrao14:05:18

Well, I donĀ“t want to use eval to make array-map, because IĀ“m reading it from edn file

fabrao14:05:50

I think there is no other way to do it

dpsutton14:05:45

I don't follow your logic of how eval got added to this

Alex Miller (Clojure team)14:05:42

reading from edn file just involves reading, not eval

Alex Miller (Clojure team)14:05:02

youā€™re not going to get ordered map guarantees out of straight edn

fabrao14:05:02

the map will be read from config file and the order of map elements is important. So if it came from edn reading, it will be hash-map not array-map, so I have to change the way to write in edn file

Alex Miller (Clojure team)14:05:40

I would recommend either using a different edn structure if you want to retain ordering

ScArcher15:05:58

When writing a function, is it bet practice to pass in a map of data, or pass in individual pieces of data as arguments? Iā€™m calling a REST API and there are a lot of optional fields. Is it best to pass required data in as arguments and optional as a map? (I know I can do & args) but it seems messy. If the best practice is a map, how do I best communicate the intent / structure of the map Iā€™m expecting?

joelsanchez15:05:03

I would go with a map and use spec for declaring required/optional fields

ScArcher15:05:56

Iā€™m onboard with passing a map. Iā€™m new to clojure, so spec seems a bit intimidating to me at this point. Any helpful guides on how to use spec in that type of situation?

ScArcher15:05:40

Thanks, Iā€™ll try this out, do you call the spec from within the function?

ScArcher15:05:07

How should the spec be associated with the function?

joelsanchez15:05:33

you can: - use spec/fdef (more advanced) - create a helper that calls spec/valid? and throws with the result of spec/explain on failure, and use that in a :pre or :post clause

joelsanchez15:05:52

(also consider using expound instead of spec/explain since it's almost unreadable)

ScArcher15:05:18

Thanks @joelsanchez I think I see how it fits together now. :pre calls spec/valid? And enforces the spec. It also communicates your intent. I think this will be great for me to start with and learn how to add additional specs to the spec/def.

joelsanchez15:05:53

basically šŸ™‚ good luck

Eddie17:05:45

New to deftype here. Is it supported (and/or does it even make sense) to add a docstring somewhere to a deftype?

Alex Miller (Clojure team)17:05:21

I could be wrong, but I do not think it is supported.

mg17:05:44

No way to look it up if you did. @erp12 what I'd suggest in this case is make a constructor function and put the docstring on that

Alex Miller (Clojure team)17:05:49

Iā€™m not sure that it could become anything useful if it did as the type turns into a class, not a var

Alex Miller (Clojure team)17:05:08

deftype could add it to the manufactured ->T constructor I suppose

Alex Miller (Clojure team)17:05:47

it generates a docstring for that already

Eddie17:05:54

ah ok. Thanks @alexmiller and @michael.gaare. I guess I could describe the type in the docstring of the helper function(s) that create the type.

Eddie17:05:19

Oh ... that is what @michael.gaare said. Sorry I am still a bit confused by the use of the word "constructor" with Clojure deftypes.

noisesmith17:05:00

->T is automatically created, and it's a clojure function that constructs an instance of T

Eddie17:05:18

Is there a name for the automatically generated functions such as .T and ->T?

noisesmith17:05:43

.T doesn't exist, T. is a shortand for new T

noisesmith17:05:01

which is interop, vm level (->T is preferred)

Eddie17:05:06

Woops put the . on the wrong side.

mg17:05:16

the deftype docstring calls ->T a constructor: ā€œOne constructor will be defined, taking the designated fields.ā€

noisesmith18:05:10

that doc string is literally talking about a jvm level constructor though, later it describes the factory function which is different

mg17:05:36

also a ā€œfactory functionā€ elsewhere

noisesmith17:05:45

it's a clojure function that acts like a vm level constructor, yeah

Eddie17:05:57

I see. ok thanks that helps a lot.

Alex Miller (Clojure team)18:05:16

->T is called a positional factory function

Alex Miller (Clojure team)18:05:56

defrecord also generates a map->T which is a map factory function

Alex Miller (Clojure team)18:05:13

but people pretty interchangeably also call these constructor functions

bortexz18:05:54

What would be an idiomatic way of finding which key in a map has a specific value? Is reduce-kv + reduced when found the best option?

bortexz18:05:07

Or would be better to ā€œinvertā€ the map so keys are vals and vals are keys, and work with that?

dpsutton18:05:53

inverting requires an invariant that all keys are distinct. also to invert it would be linear in the keys before you search for it so you may as well just search for it with reduce

dpsutton18:05:13

(clojure.set/map-invert {:a :same-key :b :same-key :c :same-key}) ;; {:same-key :c}

bortexz18:05:17

I am thinking something like

(reduce-kv (fn [m k v]
             (if condition-on-v
               (reduced k)
               m)))

dpsutton18:05:11

do you need to worry about the key not being found?

noisesmith18:05:03

why would you need reduce-kv here? I don't see what an accumulator would be for

noisesmith18:05:05

seems like you could just use (comp first (partial keep returns-k-or-nil))

noisesmith18:05:50

oh, that's just some

noisesmith18:05:17

@bertofer

user=> (some (fn [[k v]] (when (= v 0) k)) {:a 1 :b 0 :c 2})
:b

bortexz18:05:47

Ok, didnā€™t think of some, definitely makes sense!

sova-soars-the-sora19:05:37

@seancorfield i noticed that java-time does not have (interval time1 time2) implemented. is this meant to remain in joda-time only?

seancorfield20:05:06

Read http://blog.joda.org/2014/11/converting-from-joda-time-to-javatime.html where the architect of both Joda Time and Java Time explains the differences.

seancorfield20:05:11

It looks like he added an Interval type to his "ThreeTenExtra" library but there's no built-in support in Java Time. What are you using interval for in clj-time @sova?

ghadi20:05:00

In java.time there is Period and Duration

4
orestis20:05:20

I realized though that ring cookie middleware has an explicit reliance on Joda time for the cookie expiration stuff...

ghadi20:05:27

Yeah I talked to @weavejester about it a month ago. I'd really like to excise that dependency

orestis20:05:34

I guess there is a way to do dynamic requires? As in, require this if present, if not ignore?

orestis20:05:55

(This = joda time and/or Java 8 time)

dehli20:05:45

Hi all. What would be the best way to compile many different Clojurescript projects? I could cd into each project and run clojure build.clj, but then I have to start up the JVM for each project. I tried reading through the cljs.build.api docs but didnā€™t see anything.

dehli20:05:47

Another option is to have one deps.edn that pulls in all the sub projects which is what weā€™re doing now

dehli20:05:15

(the reason for it is lots of aws lambda function projects)

sova-soars-the-sora20:05:11

@dehli are you wanting to generate .js files ? you can do this from project.clj

sova-soars-the-sora20:05:35

@seancorfield interval for checking overlaps & contains

dehli20:05:03

@sova ya, i want to generate .js files. Currently I am doing it from project.clj but I want to build src thatā€™s in another project

dehli20:05:47

for example, I have build.clj in my server folder and I want to it to build server/service-a/deps.edn, server/service-b/deps.edn

sova-soars-the-sora20:05:53

seems like every time you invoke a deps.edn you're adding resolved dependencies to the classpath ... so you can probably get away with one gigantic deps.edn for all your sub projects. there may be a better way.

dehli20:05:45

thanks. thatā€™s what weā€™re currently doing but i was hoping there would be a nicer way

sova-soars-the-sora20:05:07

sounds like edn_smash is the way to go

sova-soars-the-sora20:05:31

but i encourage you to ask around because there may be others who have come across the same issue and solved it elegantly

dehli20:05:02

i wonder if i can set the classpath manually to be what the classpath of the sub project is

dehli20:05:24

donā€™t think i can do that at runtime though

andlrb21:05:26

Do tests get cached? My simple Luminus test seems to fail because of a cached timestamp from yesterday.

diff: - {:timestamp #inst "2018-05-30T21:38:27.158-00:00"}
       + {:timestamp #inst "2018-05-29T22:12:12.184000000-00:00"}

noisesmith21:05:04

anything compiled can be cached, but I'd be surprised if you were compiling test namespaces. Have you restarted your repl since then?

andlrb22:05:38

I have indeed, and the computer was shutdown too.

noisesmith22:05:14

clj or cljs?

noisesmith22:05:45

odd, lein clean will remove stray cached data (usually), but I wonder why / where that test data would be cached

dpsutton22:05:38

what does your test look like?

andlrb22:05:28

Running lein clean doesn't seem to make a difference and I receive the same result. Now, what is strange that, although it's 1AM (which means that it's already the 31th) the test result is still expecting 30th. Here's my test, note that the Luminus version is 2.9.9.2 as per the recommendation from the book I'm reading (Web Development with Clojure 2nd edition)

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

(use-fixtures
  :once
  (fn [f]
    (migrations/migrate ["migrate"])
    (f)))

(deftest test-messages
  (jdbc/with-db-transaction [t-conn db/conn]
    (jdbc/db-set-rollback-only! t-conn)
    (let [timestamp (java.util.Date.)]
      (is (= 1 (db/create-message!
                {:name    "Bob"
                 :message "Hello world"
                 :timestamp timestamp})))
      (is (=
           {:name "Bob"
            :message "Hello world"
            :timestamp timestamp}
           (-> (db/get-messages {} {:connection t-conn})
               first
               (select-keys [:name :message :timestamp])))))))

dpsutton22:05:01

i think i've run into this before. the test profile sets up a different connection so you can test in memory maybe? and when you run it not on the test profile you just side affect the db. and then you're just running predicates on it

andlrb22:05:07

I'm a tidbit too new to understand how that fully works, but I'll take another shot at it tomorrow. Thanks for your help and time! šŸ™‚

dpsutton22:05:20

so this says to use a temp db. the other one is a dev connection