Fork me on GitHub
#clojure
<
2016-06-27
>
fenak01:06:38

is there a way to destructure a map only if the values are not nil?

fenak01:06:34

i want a recursive function that matches if map has a structure or another, like: {:a 1 :d 2 :c 3} do something, {:z […]} do another

danielcompton01:06:03

@fenak maybe use contains? or select-keys?

danielcompton01:06:12

and then destructure?

seylerius02:06:32

Hmm... If I want to capture the A and foo of A_{foo}, or A and b of A_b, what sort of regex is gonna get it? I'm thinking about #"(\w)_(\S|{.*})", but I think that'll get the {}s too, and probably be excessively greedy. Ideas?

chingfan_newbie04:06:26

will this do? #"(\w)_(\S?)|{(.*)}”

onetom04:06:23

Dear all - rand seems skewed to the top-end; is this known? Why?

(->> (repeatedly 10000 #(rand 10e10))
      (group-by #(Math/floor (Math/log10 %)))
      (map (fn [[k v]] [k (count v)])))
=> ([10.0 8982] [9.0 904] [7.0 11] [8.0 101] [6.0 2])

onetom04:06:35

or more concisely:

(->>
  #(-> 10e10 rand Math/log10 int)
  (repeatedly 10000)
  (frequencies)
  (sort) (reverse))
=> ([10 8980] [9 935] [8 74] [7 9] [6 2])

smnplk05:06:11

@chingfan_newbie: probably more like this (\w)_([^{}]?)|{(.*)}

danielcompton05:06:59

@onetom: it’s just using Math.random which is presumably pretty battle tested?

smnplk06:06:50

In the docs for Math.random() it says "Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method."

chingfan_newbie06:06:27

@smnplk: right, just got vague about the meaning of \S

grav06:06:19

We have a lot of weird diffs because of indentation. What do you guys do? Do you have a hook of some kind that formats code before it’s pushed?

mpenet07:06:00

You should set proper conventions, but otherwise you can setup git conf to make this less of a problem

mpenet07:06:07

Same with the diff command, there s a flag to ignore whitespace diffs

onetom07:06:05

@danielcompton: thx. actually there is nothing wrong with the results if i do a bit more repetitions.

katox10:06:49

trying to wrap my head around clojure.spec ... what is the recommended way of doing input/output validations at program boundaries? I used schema coercers for that and it was quite handy. I'm not quite sure how to rewrite that in conformers. Suppose there is (not so reasonable) json input. What I do now is to covert it into similar edn structure - replacing strings with keywords (adjusted for clojure conventions), parsed numerical values, dates and other. Or am I supposed to just read the json, convert it and than validate the resulting edn?

katox10:06:42

Question ammend: everything in those json inputs are strings and it needs to be converted to something reasonable. Things like "jsonKey" can be converted into :json-key but I fail to see what to do with things like "1.0-2.5" which are current coerced via prismatic/schema into [1.0M 2.5M]. Hand parsing all of that is awful and it was the main reason why I used schema at all. Or should I keep the input coercer in schema and dual spec the result? Thanks for hints 😉

jindrichm12:06:56

I'm getting different results by successively applying macroexpand-1 than by macroexpand. How is that possible?

katox12:06:24

jindrichm: you're expanding a macro

jindrichm12:06:53

@katox: Yes, naturally.

katox12:06:14

jindrichm: I mean inner macro 😉

jindrichm12:06:38

@katox: "Note neither macroexpand-1 nor macroexpand expand macros in subforms." So there should be no difference, right?

katox12:06:52

jindrichm: maybe I don't get the question, macroexpand calls macroexpand-1, the source is very short

jindrichm12:06:06

@katox: Exactly. I checked the source of macroexpand and found no reason how its output can differ from successive applications of macroexpand-1. That's why I asked the question.

katox12:06:45

jindrichm: what's your code?

jindrichm12:06:40

@katox: It's quite long, so I'd have to reduce it to a minimal example.

katox12:06:53

jindrichm: I see. Macroexpand itself does what I'd call "successive aplying". No idea about the culprit in your code.

jindrichm12:06:30

@katox: I'm thinking it may be in namespaces.

lvh13:06:30

I think macroexpand just tries to find a fixpoint for macroexpand-1; I assume that’s how its implemented, but that’s my mental model

jindrichm13:06:48

@lvh: Yes, it works like that.

caio15:06:23

doubt on reader macros: I have a tag #foo/bar related to function other.ns/bar inside a library. what’s the best way to ensure that when I call #foo/bar x, the function other.ns/bar is resolved?

Lambda/Sierra15:06:20

@caio There's usually no need to use reader literals in Clojure code. Calling functions is much more predictable. Reader macros are useful primarily in EDN (data-only) files.

caio15:06:06

@stuartsierra: I agree, but it’s a large codebase (and a large number of codebases) that uses lots of reader literals. we just noticed there was a problem when I changed the require order in a namespace facepalm

Lambda/Sierra15:06:48

That's just a problem with reader literals. The correct namespace has to be loaded before the symbol is resolved.

caio15:06:14

yeah, got it 😞 . thanks anyway

seylerius16:06:12

@chingfan_newbie: That's pretty good, but the | being outside of a paren will alternate the whole expression. Either need to duplicate the whole expression or put a paren around something. Probably duplicate the missing start. Thanks!

xeqi17:06:08

Is there a way to have spec give me all the ways the input doesn't conform? Both the structure and uniqueness ones?

xeqi17:06:43

or is there a way to use s/def and s/keys to add a constraint based on a second non-global value so it can all go under ::user?

Alex Miller (Clojure team)17:06:07

@xeqi the explain, explain-data, explain-str functions will give you broader results for the failures

Alex Miller (Clojure team)17:06:43

conform/valid? take faster paths and aren’t exhaustive whereas explain* are assumed to be used in error paths and thus do more exhaustive reporting

Alex Miller (Clojure team)17:06:32

@xeqi you can use s/and to combine the s/keys with other arbitrary constraint under ::user

xeqi17:06:33

@alexmiller: validate is a local function that calls explain-data. Could have been named differently to avoid confusion, sorry

Alex Miller (Clojure team)17:06:03

ah, sorry I meant valid? :)

Alex Miller (Clojure team)17:06:40

the predicate you’re using that makes use of a stateful value is imo a bad spec

Alex Miller (Clojure team)17:06:31

specs are about structural validation, not semantic validation with stateful resources

Alex Miller (Clojure team)17:06:46

to me, that’s a different kind of validation that should be handled separately

xeqi17:06:37

kinda a blurry line, but I'll accept its not recommended for this case

katox17:06:17

as for the use case, sorry to ask again, but is json->edn coercion outside of spec scope? not parsing json, but transforming parsed json into something more clojure-y as well as verifying the final structure

Alex Miller (Clojure team)17:06:48

coercion is not in scope

Alex Miller (Clojure team)17:06:19

you can certainly leverage the results of conform plus conformers to do some transformation things (and even do them in reverse with unform) but I don’t think that full json->edn is in the scope of intent

Alex Miller (Clojure team)17:06:32

which isn’t to say you couldn’t do it :)

katox17:06:34

schema does that reasonably well, probably better than hand-written custom transformations

katox17:06:00

but I'm not very keen on having to specify both schema and spec for the result

katox17:06:00

I could do something like enabling auto transforms in json-read (keywordization, bigdec), then converting based on those keywords using conformers but it seems rather hairy

Alex Miller (Clojure team)17:06:02

the new map-of (in next alpha) will exhaustively conform and optionally conform keys so can do things like keywordization

katox17:06:42

sounds interesting, thanks

danielcompton22:06:46

(def r (range 1000))

(dotimes [_ 3]
  (time
    (dotimes [_ 10000]
      (into [] (map identity) r))))
"Elapsed time: 171.367885 msecs"
"Elapsed time: 184.365581 msecs"
"Elapsed time: 174.879711 msecs"
=> nil
(dotimes [_ 3]
  (time
    (dotimes [_ 10000]
      (mapv identity r))))
"Elapsed time: 136.176447 msecs"
"Elapsed time: 136.038665 msecs"
"Elapsed time: 142.09917 msecs"
=> nil
I assumed that mapv and into [] xf would be the same speed, but mapv is faster. I’m not quite sure why this is?

austb22:06:32

There is probably some overhead when map creates a lazy sequence and then converts it into a vector, whereas mapv goes directly to a vector

danielcompton22:06:29

I’m using a transducer though, so it should be going directly to a vector as well?

austb22:06:08

Hmmm I’ll have to admit that I’m unable to confidently answer that one. Since it’s on the order of ~10 msecs I could see that being some slight inefficiencies in the transducer, but that’s an area I can’t comment on confidently.

hiredman23:06:22

if you divide it out, you get a much smaller number per call, which my guess is the time for the extra instance? check in the transduce path