Fork me on GitHub
#clojure
<
2018-07-12
>
henrik05:07:46

I’ve never seen a deref used like this before. What does it mean?

@(def sample-data
   (->> (for [color colors size sizes type types]
          {:inv/color color
           :inv/size size
           :inv/type type})
        (map-indexed
         (fn [idx map]
           (assoc map :inv/sku (str "SKU-" idx))))
        vec))

jonahbenton05:07:39

the def returns a var, and deref, when applied to a var, "returns its current state"- so say the docs.

jonahbenton05:07:08

so it will return the results of- constructing a list of :inv/color :inv/size :inv/type maps, passed through map-indexed, and then turned into a vec

henrik05:07:48

@jonahbenton Ah, I see, thank you. So instead of returning #'some.ns/sample-data it’ll return the the contents of it.

henrik05:07:00

It did do that, but I didn’t quite understand what I was looking at.

jonahbenton05:07:14

yeah, definitely an opaque formulation for clj, though it feels idiomatic for something, but I can't place it. maybe scala is where i remember seeing phrases like that. I would guess it was written by someone working in a functional-but-not-immutable mindset.

henrik05:07:32

I guess it was written like that in order to show what’s contained in sample-data.

didibus06:07:16

Any way to trick gen-class in running at runtime?

Charleshd08:07:59

Is there a purpose difference between funcool/struct and clojure/spec ?

danielstockton09:07:32

Does anyone have a solution to the way cljfmt indents cond (I prefer the tests and expressions to be indented differently)? I have an elisp rule for cider, but I'm trying to create the same rule for those that don't use emacs.

jeremy03:07:51

Did you ever find a way to do this?

danielstockton09:07:30

This is the formatting I find much easier to read:

(cond
  t1
    e1
  t2
    e2)

jonahbenton11:07:52

@didibus (compile ...) of a namespace with gen-class doesn't produce .class files?

idiomancy15:07:36

does anyone know of any really good functional cookbooks or resources for working with really multidimensional nested data?

idiomancy15:07:56

I'm basically forming compound keys for vertical and horizontal subslices of multidimensional data and I feel like a fool. I can't do my normal pipeline approach because I have to map over the thing I'm mapping over the thing I'm mapping over 😩

idiomancy15:07:48

I'm trying to string together some crazy apply map comp stuff, and I get the distinct feeling this is like a rubiks cube that I don't know the patterns for

chrisblom15:07:30

multidimensional nested data as in arrays of arrays of arrays etc? or nested maps?

idiomancy15:07:54

its mixed. arrays of maps of arrays of arrays of maps of maps

euccastro15:07:19

are you aware of Specter? sounds like it might help with that https://github.com/nathanmarz/specter

idiomancy15:07:21

in this particular instance, it's because I'm working with hiccup. But in general I've hit these kinds of problems before and I feel like I need to find the spirit of Peter Norvig

idiomancy15:07:03

oooh, I was not aware of Specter. this looks interesting

justinlee15:07:45

+1 for specter. it is a bit tricky to learn but totally worth it

4
4
euccastro15:07:00

as for your question, this is great but you may find it slow going at the beginning, depending on your background: http://www.ccs.neu.edu/home/matthias/HtDP2e/

idiomancy15:07:46

oooh, that's awesome! a library and a "hot to get gud" class? That's outstanding!!

euccastro16:07:09

skim part five to get a feel about whether this is what you're looking for: http://www.ccs.neu.edu/home/matthias/HtDP2e/part_five.html

idiomancy16:07:31

the "Design of Computer Programs" that Peter Norvig teaches on Udacity is one of the best things I've ever done for my professional career

euccastro16:07:44

same here 🙂

😮 4
🤝 4
4
myguidingstar16:07:36

(def data-1 `{(a 1) :c})
(type (first (keys data-1)))
;; => clojure.lang.Cons
(def data-2 {(list `a 1) :c})
(type (first (keys data-2)))
;; => clojure.lang.PersistentList

myguidingstar16:07:57

how do I convert nested data with clojure.lang.Cons in it (like data-1) to normal one (like data-2)?

noisesmith16:07:37

if your code relies on the difference between cons and list, that is usually a problem with your code

alexyakushev16:07:46

What is your usecase? Things like Cons and PersistentList should usually be an implementation detail.

alexyakushev16:07:03

If you need a predicate to check for a list, I did a take on this some time ago: http://bytopia.org/2016/03/08/what-is-a-list/

myguidingstar16:07:08

@noisesmith @alexyakushev I need to validate some data with clojure.spec, but it says the data in data-1 is invalid while data-2 is ok

alexyakushev16:07:37

Is that a spec you wrote or have control over?

noisesmith16:07:41

does your spec use list? if so, don't

noisesmith16:07:51

list? is pretty much never useful

myguidingstar16:07:24

I wrote the spec

alexyakushev16:07:02

Then you've probably used a check for list? there somewhere where you shoud've used seq?

noisesmith16:07:05

really, I'd expect s/cat or s/tuple etc. rather than either...

4
alexyakushev16:07:57

It could be (s/coll-of any? :kind list?)

myguidingstar17:07:05

hmm, looks like the problem is not with the spec I wrote, but with the spec from a library I use which is a bit complex

myguidingstar17:07:27

@noisesmith @alexyakushev I'd rather stick to a solution to the question I originally asked: how to convert such nested data

noisesmith17:07:11

update-in with list*

noisesmith17:07:29

but it's a sign of a bad spec, it shouldn't care about the difference between a cons and a list

myguidingstar17:07:32

it can be in arbitrary shape

noisesmith17:07:50

then clojure.walk/post-walk with seq? and list*

myguidingstar17:07:50

so no update-in

alexyakushev17:07:03

You can use clojure.walk/postwalk then.

noisesmith17:07:28

it's still a lot of effort to accomodate a bad design

myguidingstar17:07:41

okay, I'll try

souenzzo18:07:08

Where can I find the method that turns java.util.Date into "2018-01-01T00:00:00.000-00:00" string?

noisesmith18:07:08

it's defined with the reader tags if you mean the one that has #inst right before it

souenzzo18:07:20

https://github.com/clojure/clojure/blob/e19157c4809622fcaac1d8ccca8e3f6a67b3d848/src/clj/clojure/instant.clj#L176 There is a really odd code due a bug on JVM 1.4 (?!) I will use

(-> (doto (new SimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")
      (.setTimeZone (TimeZone/getTimeZone "GMT")))
    (.format #inst"2018"))

arohner18:07:23

Does clojure.java.jdbc support executing multiple queries in the same round-trip?

joefromct18:07:20

@arohner same round trip? You mean like a transaction?

arohner18:07:52

I’d like to send two different queries at the same time, and get both result sets back in one network round trip

arohner18:07:00

I guess the same transaction, sure

joefromct18:07:15

hmm.. i mean you could do something async and a connection pool

joefromct18:07:26

why do you want to do that? maybe it'll help me understand....

joefromct18:07:59

(require '[clojure.spec.alpha  :as s]) 
(s/valid? int?     1) ;=> true
(s/valid? #(= 1 %) 1) ;=> true
(s/exercise int?   1) ;=> ([0 0])
;; ???
(s/exercise #(= 1 %) 1) ;; Spec assertion failed.  Spec: nil  Value: nil

arohner18:07:00

@joefromct let’s say querying 2 different foreign keys from the same id

joefromct18:07:14

ok... should you be just... joining them in the db?

souenzzo18:07:20

https://github.com/clojure/clojure/blob/e19157c4809622fcaac1d8ccca8e3f6a67b3d848/src/clj/clojure/instant.clj#L176 There is a really odd code due a bug on JVM 1.4 (?!) I will use

(-> (doto (new SimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")
      (.setTimeZone (TimeZone/getTimeZone "GMT")))
    (.format #inst"2018"))

jonahbenton18:07:23

hey @arohner that's usually a wire protocol capability of the underlying database. you can, for instance, send multiple queries over the wire using the mysql protocol, but it's often disabled because it can be used for sql injection

currentoor18:07:42

when you brew install clojure it installs java for you right?

noisesmith18:07:16

not in my experience

joefromct18:07:01

I don't think (not sure) postgres lets you fire multiple quiries delimited by ; if i remember correctly... sorta feels like bad form anyway (with params epsecially...?)

jonahbenton18:07:31

but if you have a table with an id and then two columns that are fks into their own lookup tables, you can get the data from the lookup tables with a single statement/join

arohner18:07:44

and then I have to un-join the result on my end

arohner18:07:53

I’m not proposing concat’ing strings

joefromct18:07:17

oh ok, so you want your results in two mutually exclusive seq's?

joefromct18:07:55

ok i might be missing it but whats wrong with this? probably not at the same time right... ?

(let  [seq-1 (j/query "select from table_one")
        seq-2 (j/query "select from fk_table") ]
...
)

arohner18:07:31

yeah, though I guess I can try futureing them

jonahbenton18:07:18

once you have a connection pool, the overhead per-query is small. there's only so much you can fit into a packet.

arohner18:07:48

I’m more worried about latency of waiting for query 1 to finish before issuing query 2

myguidingstar11:07:34

@arohner you should ask it in #sql

myguidingstar11:07:49

btw i'm also interested in this question, as it can be helpful for my sql library which makes joining and filtering tables a breeze https://github.com/walkable-server/walkable

arohner13:07:02

Ooh, I’m very interested in walkable, thanks!

myguidingstar15:07:58

walkable needs more work before it reaches 1.0 release

myguidingstar15:07:09

but at least it works now

myguidingstar15:07:10

if you have any problems, or find something hard to express with walkable, do tell me in #walkable

myguidingstar15:07:14

early adopters are hugely welcome 🙂 @arohner

joefromct18:07:51

yeah unless the db is super slow... maybe table_one is a view/aggregate over 15 million rows

joefromct18:07:03

i'd put in in an async thread

jonahbenton18:07:21

yeah, agree ^^- all drivers will allow for true parallel communication

joefromct18:07:43

j/query is greedy too, so i've been using a lot of j/reducible-query lately, but if your results fit into memory no worries

jonahbenton18:07:44

think you need to provide a generator

hiredman18:07:47

a raw predicate function like #(= 1 %) doesn't have a generator attached, and spec needs a generator to exercise the spec

joefromct18:07:17

ah ok thats why it validates but i can't build me any data

joefromct18:07:22

i saw that in the guide thank you

hiredman18:07:26

spec internally has a list of a lot of predicates from clojure.core that it implicitly has a generator for, like clojure.core/int?

👍 4
arohner18:07:01

@joefromct what version are you running? I see:

arohner18:07:23

(s/exercise #(= 1 %) 1)
ExceptionInfo Unable to construct gen at

arohner18:07:29

which is more obvious

joefromct18:07:34

[org.clojure/clojure "1.9.0"]

joefromct18:07:38

maybe it has to do with my repl

joefromct18:07:52

yeah it was dumping ^ to standard out i didn't see it