#clojure log - Jul 30 2015

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

2:22 ddellacosta: so, finally giving Stuart Sierra's component a shot, and I'm having trouble replicating the basic functionality in the repl

2:23 I suspect it's actually a referring-to-records problem vs. a problem with how I'm using component, but it seems like none of the behavior I've added to the record is actually getting performed--for example, just doing a basic assoc with 'this' similarly to how he does it in the README doesn't work

2:24 I just get the record back as it was

2:24 and printlns don't do anything either

2:24 which makes it seem like there is a no-op running vs. my actual protocol implementation

2:24 anyone seen this kind of behavior using component (or types/records in general) in the repl?

2:31 this gist shows what I'm trying to do, and how it's failing: https://gist.github.com/ddellacosta/07be4db31425f4827f1a

2:32 noidi: ddellacosta, try running lein clean before you start the repl

2:32 ddellacosta: noidi: I've restarted the repl and run lein clean a few times, don't believe that's it

2:33 will try it again once more to make sure though

2:36 yep, no luck with that (again). It's also suspicious because I've never implemented my record with no-ops--I've always had it at least printing. So I would assume that if there is some old instance of my record in memory it would be using that--but it's clearly just doing nothing.

2:57 crocket: How do I specify datetime in edn?

3:00 Oh, there is https://github.com/edn-format/edn#inst-rfc-3339-format

3:01 edn is good as a wire format.

3:01 Although it could be slower than other wire formats.

3:02 Do you use edn as your wire format?

3:18 seangrove: Is there any way to check if a value is a core.async channel?

3:20 Nooooooope http://dev.clojure.org/jira/browse/ASYNC-74

3:34 arrdem: crocket: no, don't do that, use parquet or avro or protobuffs or transit or something else

3:34 crocket: arrdem, Why?

3:34 performance?

3:35 clojurebot: http://clojure.org/java_interop#toc46

3:35 arrdem: it is possible to use edn as a wire protocol, as it is possible to use json, it's just encoding inefficient

3:35 arguably gzip streams get around some of this, but it's still a thing

3:36 at work we've reaped a huge performance win from using parquet to store lots and lots of what were previously EDN records on disk / move em over wire

3:38 But maybe you don't care, try em and see

3:38 Only You Can Profile Your Code

3:39 crocket: How do you document your wire format?

3:39 Did you document your API interface independent of wire format and wire protocol?

3:40 arrdem: Short answer is we don't, we're using parquet to move a lot of data which fits a single uniform schema and use a (could be thinner) Java layer to interact with it from Clojure

3:41 so this may not be a great datapoint for you if you're interested in a message protocol of some sort

3:41 crocket: hmm...

3:41 Probably, it is not a public API.

3:41 It's ok to not document at all if it is an internal thing.

3:42 arrdem: I mean it is documented in so much as parquet is a versioned, schema based compiled encoding and ther exist docs for the Java classes that wrap parquet encoded "objects".

3:43 but being internal and an implementation detail such docs are languishing

3:44 I thin a reasonable approach would be to design your procol first and prototype it with an EDN encoding, get that working, and then rework it to use some tighter format for performance once you have documentation and desired behavior.

3:44 but that's also Brooks' plan to throw one away which you may not be game for

3:48 ddellacosta: hmm, is it possible component isn't working for me as advertised because of Clojure 1.7?

3:48 crocket: arrdem, Is parquet for storage or wire?

3:48 ddellacosta: I just realized he says he's only tested with 1.6 and below

3:48 arrdem: crocket: it's just a data encoding you can do both with it.

3:48 socket.write(parquet.getBytes())...

3:49 crocket: we're using it for on disk (HDFS) data storage

3:51 crocket: Do you send parquet on the wire, too?

3:51 arrdem: no, that I can't speak directly to

3:52 I mean we do in so much as HDFS does it magically for us

3:52 but I'm not piping parquet data over sockets if that's the goal

3:57 crocket: What goes over the wire?

4:36 tgoossens: I have to do doseq over a possible large array (millions). Is there an easy way to parallelize this?

5:05 arrdem: Grimoire 0.4.23 live now with 1.7 special forms (issue 213/214) not broken and a minor fix or two.

5:05 sleep now

5:31 dabd: I have small app that writes some files to the filesystem. I packaged it with lein uberjar. If I call -main from the REPL it works fine, however if I run it from the cmd line it won't write anything. Anything I am missing?

5:34 Kneiva: dabd: how do you run it from command line?

5:34 dabd: with java -jar <standalone jar> arg1 arg2 ...

5:36 I think I found the problem. The side effects were being called inside a 'map' which is lazy and probably the repl forces the evaluation which won't happen when I call it from the cmd line. I switched the map to run! and now it works

5:36 Kneiva: great

5:36 dabd: does this make sense?

5:36 Kneiva: yes

5:37 dabd: supposing I wanted to use map how do I force the evaluation?

5:38 MasseR: dabd: haven't written clojure for a while, but wasn't there something like doseq which forces evaluation?

5:38 Use map for pure computations and doseq for side-effects

5:40 dabd: yes makes sense

5:58 cfleming: Somewhat OT: I just know enough IRC to get connected and then not touch anything. Recently for some reason I started receiving private messages from *status every time I connect to my ZNC instance. Does anyone know how to disable that? I'm using Textual on OSX.

7:07 perplexa: gfredericks: didn't you put up some black magic 'timestamps' created only with the java math lib? can you gimme a link pls?

7:20 Cka3: Hello, can someone help me? I need to figure out how to get from two collections e.g. [2 8 6] [8 5 1] one collection of collections like this ([2 8 6][3 7 5][4 6 4][5 5 3][6 5 2][7 5 1][8 5 1]) ?

7:21 alexyakushev: Cka3: Where are the other elements coming from?

7:21 zphds: Cka3: you could flatten the source coll and use permutations

7:21 http://clojure.github.io/math.combinatorics/

7:22 alexyakushev: zphds: It doesn't look lke permutations, more like reducing the last number and increasing the first one, but still unclear

7:22 Cka3: here is my first step

7:22 zphds: alexyakushev: yes, you're right

7:22 snowell: Looks like it's showing intermediate steps to transform the first one into the second one

7:22 Using inc and dec

7:22 Cka3: (let [from-color [2 8 6]

7:22 to-color [8 5 1]

7:22 step 1

7:22 direction (fn [a b] (map #(if (> %1 %2) - +) a b))

7:22 crange (fn [a b c] (conj (vec (range a b (c step))) b))

7:22 ]

7:22 (map crange from-color to-color (direction from-color to-color)))

7:23 => ([2 3 4 5 6 7 8] [8 7 6 5] [6 5 4 3 2 1])

7:23 I'm very new to programming)

7:24 ([2 8 6][3 7 5][4 6 4][5 5 3][6 5 2][7 5 1][8 5 1])

7:24 this what I need to get)

7:28 Any ideas? ))

7:29 Rich? )

7:29 justin_smith: Cka3: don't do multiple line pastes, please. Use a site like refheap.com for that

7:30 Cka3: Sorry

7:31 justin_smith: Cka3: your "c" argument to crange needs to be a function you can call, and direction does not return a function

7:32 actually to be correct, direction would have to return a sequence of functions

7:32 or you would have to do something with c other than calling it

7:33 Cka3: it returns collection of functions + or -

7:33 justin_smith: oh, wait, never mind, it does return a sequence of functions

7:33 right

7:33 Cka3: but I having problem with the next steps

7:34 how I can go from this ([2 3 4 5 6 7 8] [8 7 6 5] [6 5 4 3 2 1]) to this ([2 8 6][3 7 5][4 6 4][5 5 3][6 5 2][7 5 1][8 5 1])

7:34 justin_smith: Cka3: (apply mapv vector) will give you your answer

7:35 ,(apply mapv vector '([2 3 4 5 6 7 8] [8 7 6 5] [6 5 4 3 2 1]))

7:35 clojurebot: [[2 8 6] [3 7 5] [4 6 4] [5 5 3]]

7:35 justin_smith: except one of your sequences is too short, you need to fix that

7:35 Cka3: no I don't)

7:35 justin_smith: OK, then don't use the simple solution

7:35 and fix it some other way

7:37 Cka3: the straightforward solution would be to fill the short inputs by repeating the last element until they are equal in length to the longest

7:37 followed by mapv vector

7:37 Cka3: so I need to check which collection is longest and then for other two collections fill missing items with last element of themselves?

7:38 justin_smith: or you could use a loop

7:43 the loop version is a lot uglier

7:48 Cka3: this gives the right answer, but it is ugly I think https://www.refheap.com/107264

7:56 Cka3: I updated the paste above, maybe the second version is a bit better

8:02 Cka3: thank you!

8:04 gfredericks: perplexa: I think what you're remembering was just some tweets, and I can't search twitter effectively enough to find them; but this is related https://gist.github.com/gfredericks/96e284ce2d52b91d481e

8:05 oh just kidding, searching for "Math/cbrt" worked: https://twitter.com/gfredericks_/status/517622176821043200

8:06 justin_smith: gfredericks: OH, I remember when we were mucking with that stuff!

8:07 making arbitrary doubles using only java.lang.Math and no literals

8:11 perplexa: gfredericks: thanks

8:13 gfredericks: justin_smith: I don't think I succeeded in getting arbitrary doubles; I got pretty close though

8:13 I think arbitrary integers for sure

8:14 though I guess in the 2^53 range that's about the same problem

9:06 jonathanj: user=> "\003"

9:06 ""

9:07 i'm assuming that the \003 is elided from the REPL output there because it's not printable, but how can i actually be sure?

9:14 opqdonut: jonathanj: try (seq "\003") to look at the characters in the string

9:15 ,(seq "\012\141") -- like this

9:15 clojurebot: (\newline \a)

9:15 opqdonut: ,(seq "x\003x")

9:15 clojurebot: (\x \ \x)

9:16 opqdonut: well that looks weird

9:17 justin_smith: ,(first "\003")

9:17 clojurebot: \

9:17 justin_smith: haha

9:17 opqdonut: ,(seq (.getBytes "\003"))

9:17 clojurebot: (3)

9:17 opqdonut: so it really is there

9:18 ,\o003

9:18 clojurebot: \

9:18 opqdonut: ,\o004

9:18 clojurebot: \

9:18 opqdonut: hrmph

9:19 ,[\o010 \o016]

9:19 clojurebot: [\backspace \]

9:19 opqdonut: right, clojure probably just prints \<the character> when you don't hit one of the \tab \newline etc. special cases

9:19 or rather, tries to print

9:20 justin_smith: ,(apply str [\a \backspace \b])

9:20 clojurebot: "a\bb"

9:20 justin_smith: hrmph

9:20 ,(print (apply str [\a \backspace \b]))

9:20 clojurebot: ab

9:41 tgoossens: given a map m , how can i update the values of m (for all keys) given a transform fn

9:41 justin_smith: ,(into {} (map (fn [[k v]] [k (inc v)]) {:a 0 :b 1 :c 2}))

9:41 clojurebot: {:a 1, :b 2, :c 3}

9:42 tgoossens: <3 destructuring, justin_smith thanks!

9:42 justin_smith: or ##(reduce-kv (fn [m k v] (assoc m k (inc v))) {} {:a 0 :b 1 :c 2})

9:42 lazybot: ⇒ {:a 1, :b 2, :c 3}

9:44 snowell: Is using `for` more/less efficient than map/reduce?

9:44 Ah, he did say "given a transform fn"

9:45 Turns out the best way for me to read something is to hastily reply to it :/

9:45 justin_smith: snowell: for should be pretty much equivalent to map

9:45 i-blis: snowell, I think the difference might come from into vs .kvreduce

9:46 into uses transients (and I guess reduce doesn't use mutation)

9:47 justin_smith: the reduce-kv version could easily be updated to use transients, of course

9:48 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (tansient {}) {:a 0 :b 1 :c 2})

9:48 ,(persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (tansient {}) {:a 0 :b 1 :c 2})

9:48 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

9:48 justin_smith: err

9:48 i-blis: yeap, one could wrap it in persistent!

9:48 justin_smith: ,(persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (tansient {}) {:a 0 :b 1 :c 2}))

9:48 clojurebot: #error {\n :cause "Unable to resolve symbol: tansient in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: tansient in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6611]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: tansien...

9:48 justin_smith: hmm

9:48 ,(persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) {:a 0 :b 1 :c 2}))

9:48 clojurebot: {:a 1, :b 2, :c 3}

10:23 csd_: Is it possible to have `lein repl`, when run inside a project dir, *not* execute the project's top level forms?

10:24 justin_smith: csd_: you can not specify a :main, you can use lein run -m clojure.main to launch a vanilla repl that does not load your project

10:24 but that's not going to be an nrepl, of course

10:24 csd_: justin_smith: would that still allow access to the project deps as needed?

10:24 justin_smith: csd_: via require, yes

10:25 csd_: cool thank you

10:26 justin_smith: csd_: lein is hella convenient, but I think there's something to be said for knowing how to set things up by hand too

10:26 csd_: another unrelated question-- my coworkers are telling me that an uberjar can only package up clojure deps, and not java deps. so instead we're using an eclipse package that does this but its really clunky. do you know of any alternatives?

10:27 justin_smith: csd_: :provided in project.clj should prevent the dep from being packed into an uberjar

10:27 csd_: no we want to have an uberjar that has every dependency in it, whether clojure or java based

10:28 justin_smith: csd_: oh, they are claiming a clojure uberjar is unable to contain java deps? that's patently false

10:28 just add the java dep to your dependencies, it just works

10:28 I thought they were saying those deps should be excluded

10:28 csd_: hrm i don't know then

10:29 clgv: csd_: uberjar it is then ;)

10:30 justin_smith: csd_: well anyway, if your uberjar was including a thing erroneously, you can use the :provided {:dependencies [things you want but not in uberjar]} thing, and for java deps you do want in an uberjar, you just convert the maven coordinates to lein notation, which is easy, and put them under :dependencies

10:30 TimMc: csd_: Every uberjar I've ever made disagrees with their claim.

10:30 csd_: i see

10:30 would this still work for java dependencies that are accessed locally and which arent hosted on maven/etc?

10:31 justin_smith: csd_: you would need to at least run lein install, or put them in resources/ or something

10:31 (or mvn install or whatever)

10:31 it's really not hard to make a maven accessible jar of something

10:31 clgv: justin_smith: putting them in resources requires some serious weight lifting to load them afterwards ;)

10:32 justin_smith: csd_: like adding resources/foo.jar to your classpath?

10:32 err, that was for clgv

10:32 csd_: ok well idk what they're talking about then

10:32 clgv: justin_smith: would work from leiningen but not from the uberjar afaik

10:33 justin_smith: clgv: but yeah, the better solution is to put the jar into a maven repo

10:33 clgv: resources end up in your uberjar

10:33 clgv: csd_: for repeatable builds from different dev machines you should host those dependencies anyway

10:33 csd_: yeah

10:33 clgv: justin_smith: that's true but there is no eays way to add a jar within a jar to the classpath

10:33 csd_: just a lot of other things need doing too :-P

10:33 justin_smith: yeah, we use s3-wagon-private, but I think we should upgrade to a regular private maven server

10:34 clgv: csd_: but broadcasting new deps is annoying as well, isnt it?

10:34 csd_: it really only applies to two things, and one of them is fairly stable

10:34 clgv: csd_: not to mention potential inconsistencies

10:35 csd_: we have a hacked version of one serialization library, and the other is our java platform code which we export some of into a jar

10:35 the serialization library has been fairly stable

10:35 clgv: setting up a repository is not that hard

10:37 csd_: do you know of a good guide?

10:38 clgv: csd_: those repository tools usually have their guide. I checked archiva and nexus where that is the case

10:38 justin_smith: csd_: iirc nexus has a good walkthrough

10:42 clojure: help me ? "Cannot cast clojure.lang.PersistentVector to [Ljava.lang.Class;" my code: (def ctor (-> clazz (.getDeclaredConstructor [String, String, int])))

10:43 help me ? i got a exception: "Cannot cast clojure.lang.PersistentVector to [Ljava.lang.Class;" here is my code: (def ctor (-> clazz (.getDeclaredConstructor [String, String, int])))

10:43 csd_: How do I refer to a Java compiled class (Foo.class) in clojure? I'm getting a class not found error. Specifically this is to mimic something like Guice's Key.get(Thingie.class, annotation) syntax

10:46 clgv: clojure: read that blog post (or tutorial) more carefully

10:48 noncom|3: speaking of idiomatic clojure.. if you have some program or a script, big enough to be spread over several namespaces, and which conducts some process, do you prefer to pass the state among all the functions in the program or do you reside to storing it in an atom?

10:49 i find storage in atom far more convenient in most occasions, however, i wonder what others think..

10:49 TimMc: clojure: Do you need help understanding the exception?

10:49 Or what?

10:51 noncom|3: clojure: i think you need (into-array [String, String, int]) ... ?

10:51 coz [] is not [Ljava.lang.*

10:52 csd_: even better - push you library to clojars and enjoy the eternal benifits of repeatability right away!

10:54 clgv: csd_: use only the class name itself

11:00 jonathanj: so there was no real consensus as to how i get \003 to usefully display in a REPL?

11:01 it would be nice if non-printables were just printed in their escaped octal form

11:03 opqdonut: jonathanj: indeed it would

11:03 jonathanj: can i file a bug somewhere?

11:03 noncom|3: in jira?

11:04 opqdonut: jonathanj: you could just use StringEscapeUtils to get the escaped string back, but yeah, file a bug

11:04 noncom|3: or maybe in the issue tracker of the particular repl you're using...

11:05 jonathanj: does the REPL itself construct the representation?

11:22 noncom|3: jonathanj: not sure what you mean... repl is the one who presents you the data

11:22 i think that you can sorta change this data before it presents it to you

11:23 other details depend on the particular repl you use

11:23 clgv: jonathan: prn

11:23 ,(prn \003)

11:23 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported character: \003>

11:23 tmtwd: Are there any libraries for putting in html and spitting out hiccup?

11:24 clgv: huh?

11:24 ,(prn (char 3))

11:24 clojurebot: \\n

11:26 jonathanj: i'm not sure how it works with Clojure, but with Python presenting a representation of data is generally up to the data type via the repr() API

11:26 clgv: jonathan: clojure has the print-method multi method

11:27 jonathanj: can i determine whether there is a method defined for a particular type?

11:28 anyway, is it truly solely up to the REPL to determine how best to display the result of every value?

11:29 clgv: jonathan: as I said, that is the task of the print-method

11:30 jonathanj: okay, so filing the bug against the REPL i'm using is probably not the right course of action

11:30 clgv: jonathanj: indeed.

11:31 jonathanj: you can look up the types via ##(keys (.getMethodTable print-method))

11:31 lazybot: ⇒ (nil java.lang.Boolean clojure.lang.Var java.lang.Character clojail.testers.ClojailWrapper clojure.core.Iteration java.util.Date java.lang.Class java.util.RandomAccess java.util.regex.Pattern java.util.UUID :default clojure.lang.ISeq java.sql.Timestamp clojure.lang.... https://www.refheap.com/107273

11:33 clgv: jonathanj: you can override as follows: (defmethod print-method Character [x, w] (.write w (format "char: %s" (long x))))

11:34 jonathanj: though that only handles single characters

11:41 tmtwd: I meant if there are any libraries that let you input raw html and outputs hiccup-html

11:41 that way I can paste templates from bootstrap and use hiccup instantly

11:49 * gilliard is surprised that crouton doesn't output the format that hiccup uses

12:20 csd_: is there any other magic i need to do to get slamhound.el working other than jacking in with cider? It looks like it's having trouble talking to the nrepl

13:08 dabd: anyone has an idea what the function parse-opts from tools.cli expects as first argument? (parse-opts ["-h"] ["-h" "--help"])

13:08 throws an exception

13:09 I meant (parse-opts ["-h"] [["-h" "--help"]])

13:32 TimMc: lgtm

13:46 slester: Is there accepted style for using (cond->)? Do I just use a space after each condition or do I line up conditions and functions?

14:07 kwladyka: I am so confuse... i have my own algorithm in Clojure and i have not my algorithm in Scala. This one in Scala run in 1 sec, but my don't stop after 30 minuts. As i see they do exactly the same.... somebody is able to help me understand why is that?

14:08 bja: are you sure they are the same?

14:08 (i.e. not using mutable ops in scala)

14:08 kwladyka: if i see good they do the same

14:09 bja: do you have an example somewhere (maybe a gist)?

14:09 kwladyka: https://github.com/VlachJosef/scalac-chess-problem/tree/master/src/main/scala/vlach/josef <- scala super fast

14:10 my, the most important part https://www.refheap.com/76772dd5a7946a727450d76bb

14:10 scala use bfs and my use dfs but as i know there is no difference

14:11 *no difference in complexity

14:11 justin_smith: I wonder why clojure-mode wants to highlight "handle" as if it were special...

14:12 kwladyka: i have maybe a little mess in code because i was changing it so many times and still looking right one

14:12 justin_smith, can i please you to look on my question? i am fighting with this so long

14:13 do you see any mistake in my code which can make it slow?

14:13 or why scala code is so fast?

14:13 it doesn't make sense

14:15 justin_smith: kwladyka: for starters your recursive-solutions is not tail-recursive, unlike the scala version

14:16 the only way to do tail-recursion in clojure is recur, though you could also use loop or trampoline to the same effect

14:17 kwladyka: justin_smith, but is it changing anything if i will use recur instead of name of function?

14:17 in performance

14:17 but ok, i can change the name to recur, it should works without changing anything else

14:18 but still it is slow

14:18 justin_smith: kwladyka: no, "changing the name to recur" doesn't do it

14:18 kwladyka: ok, i can't change it so easy

14:19 justin_smith: and yeah, you can't just swap out the self call - you have to change how the stack is being managed

14:19 kwladyka: before i was using recur with loops and it was also slow

14:19 justin_smith: also, eventually you would want something other than doseq anyway, because otherwise your function will always return nil

14:19 ,(doseq [i (range 10)] i)

14:20 clojurebot: nil

14:20 kwladyka: justin_smith, because the solutions is only on the end of tree i am using ref variable

14:20 and change it only if i am on the end of tree

14:21 so i dont have to return anything

14:21 justin_smith: OK

14:21 kwladyka: so... am i using something what is slow?

14:21 justin_smith: btw, a ref-set that uses the existing value should be replaced with alter (see line 10)

14:22 kwladyka: yes, primitive recursion is slower than a loop or tail recursion via recur. Using a ref is slower than passing a value along to hold results

14:23 kwladyka: justin_smith, ref is not exaclty a problem, there is only 92 call this in example what i am trying do faster

14:24 justin_smith, hmm but loop and recur is not lazy?

14:24 justin_smith: no, it is not

14:24 nor is self call

14:24 which is what you do now

14:24 neither is lazy

14:25 the only thing that is lazy is lazy-seq (or one of our many helpful functions that use lazy-seq)

14:25 kwladyka: that doseq on line 64 is not lazy, it will call the function again for every result, eagerly

14:25 kwladyka: justin_smith, so do you think if i will rewrite it with loop and recur it will change it from 40 minuts to 1 second? ;)

14:26 justin_smith: kwladyka: I have no idea, but I suspect that you are wasting CPU cycles in that eager doseq with self calls on line 64

14:26 because that is driving your algorithm, and it is not in any way lazy

14:26 nor is it fast - you want one or the other at least

14:27 kwladyka: what else can i check?

14:28 justin_smith: kwladyka: I have no idea, I've got other stuff I need to attend to at work, sorry

14:28 kwladyka: justin_smith, ok, thank you for help

14:28 just.... i cant live with this problem, i am spending hours on that why it is so slow..

14:29 everyday

14:29 :)

14:29 justin_smith: kwladyka: I suspect the solution will involve replacing the doseq with something lazy

14:31 kwladyka: i was trying do this in so many ways... but i will try again, each time i am clever :)

14:31 justin_smith: also the concat on line 22, you'd get a faster result by replacing all those filters with one group-by followed by some key lookups

14:32 wait, no, just use frequencies

14:32 ,(frequencies [:queen :queen :rook :rook :rook :bishop :knight :bishop :knight :king])

14:33 clojurebot: {:queen 2, :rook 3, :bishop 2, :knight 2, :king 1}

14:34 justin_smith: if you really need that format ##(sort-by (zip-map [:queen :rook :bishop :king :knight] (range)) [:queen :queen :rook :rook :rook :bishop :knight :bishop :knight :king])

14:34 lazybot: java.lang.RuntimeException: Unable to resolve symbol: zip-map in this context

14:34 justin_smith: ,(sort-by (zipmap [:queen :rook :bishop :king :knight] (range)) [:queen :queen :rook :rook :rook :bishop :knight :bishop :knight :king])

14:34 clojurebot: (:queen :queen :rook :rook :rook ...)

14:34 justin_smith: much faster than 5 filters and a concat

14:38 slester: justin_smith, my game is coming along slowly. Still trying to parse/determine what you were saying about passing along snapshots of the game state as a lazyseq

14:39 TEttinger: slester: ah!

14:40 I had an idea for that

14:40 https://github.com/tommyettinger/infinite-raid/blob/master/src/infinite_raid/state.clj

14:40 pretty simple state tracking, it needs an RNG with a highly visible state, so you can get and reseed the RNG to earlier states

14:42 justin_smith: slester: in a functional language, you can replace any global state with a sequence of values, which each value is a snapshot in time

14:43 TEttinger: what's the reasoning for repeated swap! calls on the same atom? why not one assoc with multiple keys and vals?

14:44 TEttinger: the order is guaranteed ##(assoc {} :a (doto 1 pr) :b (doto 2 pr) :c (doto 3 pr))

14:44 lazybot: ⇒ 123{:c 3, :b 2, :a 1}

14:44 TEttinger: justin_smith: http://i110.photobucket.com/albums/n86/MCRfreek92/i-have-no-idea-what-im-doing-dog.jpg

14:45 justin_smith: haha

14:45 kwladyka: thx

14:45 justin_smith, thx

14:45 justin_smith: TEttinger: the reason I ask, is atoms have a relatively high overhead for modification, so if you reduce the number of swap! calls you'll usually see a benefit

14:45 hellofunk: justin_smith: doesn't that replacement of values kinda depend on persistent data structures? not all functional languages actually implement their data in the way Clojure does

14:45 TEttinger: yah, I haven't touched that code in a while

14:46 justin_smith: hellofunk: you could do a full tree copy in a language that doesn't have immutable values

14:47 hellofunk: the only difference is that it's up to the programmer to be disciplined and not touch the history (rather than enforced fairly strongly by the language itself)

14:47 hellofunk: that's one of the things that really bugs me about Swift. they have all these seductive functional idioms everywhere, but the data is fully copied when you actually "change" anything

14:47 TEttinger: I was wondering about using in-memory file serialization to mimic clojure in lua

14:48 justin_smith: yeah, and what's worse, they lead naive users to think that functional programming implies that kind of slow deep copying everywhere

14:48 hellofunk: it's awful.

14:48 justin_smith: so they try fp in swift and are like "never mind, fp is too slow"

14:48 hellofunk: i'm saddened that apple didn't do more under the hood. but that's probably why they are open sourcing the language, they want the community to fix it

14:48 TEttinger: https://github.com/torch/torch7/blob/master/doc/file.md#serialization-methods

14:54 slester: TEttinger, thanks, I'll look at it! I'm still a newbie to clojure/functional programming so it's taking me a while to process things.

14:56 gfredericks: hello

14:56 kwladyka: justin_smith, can you recommend me something to watch / read about how to write algorithm with good performance. I mean for example to use recur instead of primitive recur and use lazy instead of eager, but with explanation why and what is happening inside? to better understand how to write fast code?

15:00 justin_smith: slester: what I had in mind was somthing much simpler - imagine a game where :a and :b repeatedly flip a coin and keep a tally ##(iterate #(update % (if (> 0.5 (rand)) :a :b) inc) {:a 0 :b 0})

15:00 lazybot: java.lang.RuntimeException: Unable to resolve symbol: update in this context

15:00 justin_smith: ,(iterate #(update % (if (> 0.5 (rand)) :a :b) inc) {:a 0 :b 0})

15:00 clojurebot: ({:a 0, :b 0} {:a 1, :b 0} {:a 2, :b 0} {:a 2, :b 1} {:a 2, :b 2} ...)

15:01 justin_smith: an immutable lazy seq containing every state the game reaches, in order

15:01 ,(iterate #(update % (if (> 0.5 (rand)) :a :b) inc) {:a 0 :b 0})

15:01 clojurebot: ({:a 0, :b 0} {:a 0, :b 1} {:a 1, :b 1} {:a 2, :b 1} {:a 3, :b 1} ...)

15:03 slester: justin_smith, ah! I'm kind of going to be doing that in a way. I have state, and I just recur until the state's "over" flag is set to true

15:04 justin_smith: slester: right, you could even use take-while with iterate if you wanted the full history instead of just the final state

15:04 slester: I'm hesitant to show code because it's probably awful

15:04 ah, nice idea

15:04 justin_smith: heh, remember it's a great way to learn if your ego can handle the bruising

15:04 slester: it can, I just don't want to waste people's time

15:06 justin_smith: kwladyka: sorry about the delay - that is a huge subject and I can't think of something simple off the top of my head - it's likely covered in a functional way in SICP? https://mitpress.mit.edu/sicp/full-text/book/book.html which is a great textbook, available for free online, in a language very similar to clojure

15:07 hmm maybe that doesn't cover run time complexity actually...

15:09 kwladyka: you could check out using clojure.tools.trace to see how much each of your functions is getting called

15:10 slester|lunch: justin_smith, https://github.com/slester/amiss is the code if you're interested. I'll be back after lunch!

15:10 maybe PM would be best?

15:10 appreciated if you do have time

15:12 justin_smith: slester|lunch: on line 66, you don't need partial ##(apply + 1 [2 3])

15:12 lazybot: ⇒ 6

15:13 justin_smith: ,(map (comp {-1 false 0 nil 1 true} compare) [1 2 3 4 5] [5 4 3 2 1])

15:13 clojurebot: (false false nil true true)

15:14 justin_smith: slester|lunch: ^ suggestion for compare-cards

15:15 slester|lunch: on line 106 the two assoc-in calls could be replaced with a single assoc

15:17 ,(< 1 2 5) ; slester|lunch - suggestion for line 168

15:17 clojurebot: true

15:28 amalloy: Bronsa: re clj-1460 it may be helpful to know that clojure.core/case macroexpands to something involving a sorted-map

15:30 or maybe an array-map? i forget. at any rate if you macroexpand a case statement yourself and then eval it, and that case has "too many" clauses, stuff breaks because the cases are no longer in the right order

15:31 Bronsa: amalloy: yeah that's how I discovered that bug actually

15:31 amalloy: i wonder if you heard about it from me complaining about that issue in here, ages ago

15:32 Bronsa: amalloy: i wish i had. I remember spending hours trying to figure out why t.e.jvm was bugged.

15:33 amalloy: ah. for me, it came up trying to use c.t.macro/macrolet

15:33 where i wound up let'ing a macro that involved a 10-clause case

15:33 Bronsa: fun times debugging that stuff I bet

15:35 amalloy: i've been bitten by macrolet like 5 different times in 5 different ways, and yet the siren song of macrolet always calls me back

15:38 sdegutis: My intuition about partition-by at some recent point became no longer in sync with reality.

15:39 I assumed (partition-by (partial = :z) [:a :b :z :c :d :z :e]) would give '((:a :b) (:c :d) (:e)) but it's actually giving '((:a :b) (:z) (:c :d) (:z) (:e))

15:48 justin_smith: sdegutis: so you were imagining it to behave like string/split does

15:48 sdegutis: I suppose yes.

15:49 In fact the first function I Dash'd was split-with.

15:49 Then I realized I probably wanted something more like partition-by.

15:49 (Since I wanted it to happen multiple times, not just once.)

15:51 Right now I'm just combining that `partition-by` with (remove (partial = [:z]) ...)

15:51 Seems to work, but feels sloppy and careless.

15:51 tear: -------------------------------------------------

15:56 wasamasa: smooth

16:05 Bronsa: amalloy: looks like it is documented that (eval (sorted-map 1 1)) is allowed to return a PAM :/

16:10 slester: justin_smith, thanks, looking at those now

16:12 sdegutis: wasamasa: I don't get it.

16:13 slester: ,(compare 1 5)

16:13 clojurebot: -1

16:13 slester: justin_smith, I think I was under the impression that it returned like, -4

16:14 wasamasa: sdegutis: I guess you didn't see that /quit

16:15 sdegutis: wasamasa: I have them hidden. Much quieter this way: https://www.dropbox.com/s/8qh22b5vn6x5e6f/quieterirc.png?dl=0

16:15 wasamasa: sdegutis: smart filter ftw

16:16 sdegutis: wasamasa: what was it?

16:16 wasamasa: sdegutis: tear got immediately k-lined after posting

16:17 sdegutis: Ha.

16:24 How do you get the current year. Thanks.

16:25 justin_smith: ,(.getYear (java.util.Date.))

16:25 clojurebot: 115

16:25 justin_smith: you probably want to add 1900

16:25 ,(+ 1900 (.getYear (java.util.Date.)))

16:25 clojurebot: 2015

16:26 Bronsa: sdegutis: you keep asking questions not related to clojure that you could answer yourself with 20 seconds of google, could you try doing that next time before asking?

16:27 sdegutis: Thanks, I used the Clojure library chee.datetime.

16:27 ,(do (require '[chee.datetime :as dt]) (str (dt/year (dt/now))))

16:27 clojurebot: #error {\n :cause "Could not locate chee/datetime__init.class or chee/datetime.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate chee/datetime__init.class or chee/datetime.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java" 419]\n [clojure.core$load$fn__...

16:29 justin_smith: sdegutis: lol top google hit for chee.datetime https://github.com/slagyr/joodo/issues/27

16:31 jsabeaudry: Is there a csv library for clojurescript ?

16:31 sdegutis: Most likely.

16:32 Bronsa: jsabeaudry: https://cljsjs.github.io/ looks like there are a few

16:33 ah nevermind, those are js libraries

16:33 https://github.com/testdouble/clojurescript.csv this seems what you need otoh

16:33 sdegutis: justin_smith: how is that lol?

16:34 jsabeaudry: Bronsa, thanks for the first link

16:34 Bronsa, that second one cannot read csvs haha

16:34 sdegutis: Bronsa: Sometimes #clojure surprises me with very excellent pure-Clojure answers that aren't in the top Google results.

16:35 Bronsa: sdegutis: "how to get the current year" is hardly a question you'd expect to get such an answer

16:35 sdegutis: Bronsa: You never know!

16:35 :)

16:52 slester: it's why I try to google and understand things before I ask here, and why I'm afraid to actually post code snippets until I've tried to vet them myself heh

17:01 phyzome: slester: As long as it's clear you're putting in some effort of your own it's fine to ask questions and link to snippets!

17:09 jsabeaudry: Somehow the cljsjs does not get compiled when I run my project? Is there anything I need to do when a lein project has boot dependencies?

17:17 justin_smith: Bronsa: in fact, people fear, mistrust, and commonly misuse java.util.Date, and will go through all kinds of silliness to avoid the simplest answer if the simplest answer is to use Date

17:19 like a wrapper library that makes a calender out of a data and pulls the year out of the calendar

17:27 oddcully: and because Date is so awesome, there is a new api in each major java version

17:35 numberten: is there a place you can add let variables in a prop/for-all with test.check?

17:35 instead of recomputing a constant for every test

17:36 sdegutis: justin_smith: on the other hand, an API that is easy to misuse is poorly designed

17:48 TimMc: I've certainly never heard someone claim that Date was well-designed. :-)

17:54 sdegutis: Is there a way that I can make (require 'foo.bar) look in "src/foo/bar/[something].clj" instead of "src/foo/bar.clj" ?

18:04 Thanks.

18:09 numberten: is there something like clojure.test's 'thrown?' that you can use in test.check?

18:16 sdegutis: Why isn't this true? &&(= {:a 2} {:a 2 :b nil})

18:16 Oops I forgot the bot notation.

18:17 Cr8: ,[(:b {:b nil} :missing) (:b {} :missing)]

18:17 clojurebot: [nil :missing]

18:17 sdegutis: Oh.

18:17 Still, it seems that in the general case, nil and absent should be equivalent.

18:18 Cr8: ,(mapv seq [{} {:b nil}])

18:18 clojurebot: [nil ([:b nil])]

18:19 Cr8: ,(map (partial contains? :b) [{} {:b nil}])

18:19 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.Keyword>

18:19 Cr8: ok i got something wrong there but you get the idea

18:19 lots of respects in which containing a k-nil pair is different than not having an entry for k

18:20 you couldn't even roundtrip JSON through if that were the case

18:21 sdegutis: I assumed for maps that (= m1 m2) would be equivalent to (every? #(= (% m1) (% m2)) (distinct (concat (keys m1) (keys m2))))

18:21 That seems like the most common-sense meaning of = for maps.

18:22 Bronsa: equality on maps uses contains?, not get

18:22 which is the reasonable thing to do

18:22 justin_smith: ,(= {Double/NaN Double/NaN} {Double/NaN Double/NaN})

18:22 clojurebot: false

18:22 Cr8: https://github.com/clojure/clojure/blob/b926222fbdbd866806d441fa362e3ac0cf0afafa/src/jvm/clojure/lang/APersistentMap.java#L52-L71

18:23 Bronsa: sdegutis: would you have two maps be equal when their `count` differs?

18:23 Cr8: checks pair count is the same, checks contains for each key, then checks get equivalence

18:23 Bronsa: ,[(count {:b 1 :a nil}) (count {:b 1})]

18:23 clojurebot: [2 1]

18:23 sdegutis: Bronsa: because (= (get m1 :b) (get m2 :b))

18:23 Bronsa: so what?

18:23 (not= (contains? m1 :b) (contains? m2 :b))

18:23 what's your point?

18:24 sdegutis: Bronsa: so it seems intuitive to me that they're equal when (get) for all keys produce equal results

18:24 justin_smith: sdegutis: so (= {:a 0} {:a 0 :b 1 :c 2}) by that argument

18:24 Cr8: if (get) was the only thing on the map interface that would make sense

18:24 it's not

18:24 Bronsa: sdegutis: and contains? does not.

18:24 nor does count on the map

18:24 sdegutis: justin_smith: No, that would be false.

18:24 Bronsa: a nil key is not a non-present key

18:24 Cr8: plus also there's get of other arities that isn't the same

18:24 sdegutis: justin_smith: either you're completely misunderstanding what I said, or I completely butchered saying it.

18:25 Cr8: ,[(get {:b nil} :b :missing) (get {} :b :missing)]

18:25 clojurebot: [nil :missing]

18:25 Cr8: or:

18:25 nil doesn't mean "not present", it's just the default default value

18:26 justin_smith: ,((juxt = list) (hash-map Double/NaN Double/NaN) (hash-map Double/NaN Double/NaN Double/NaN Double/NaN))

18:26 clojurebot: [false ({NaN NaN} {NaN NaN, NaN NaN})]

18:26 sdegutis: The fact that the /default/ for get on a map with an absent key is nil seems to suggest that the :missing key is an exception for special circumstances, and that in the general case, you shouldn't care whether the key pointed to a literal nil or missing.

18:26 And = should assume the general case, not the exception.

18:27 Bronsa: that's not how equality works.

18:27 sdegutis: Bronsa: Honestly I think you just want to defend whatever Clojure currently does without regard to what it ought to do.

18:27 Bronsa: sdegutis: lol.

18:29 justin_smith: ,(iterate #(assoc % Double/NaN Double/NaN) {})

18:29 clojurebot: ({} {NaN NaN} {NaN NaN, NaN NaN} {NaN NaN, NaN NaN, NaN NaN} {NaN NaN, NaN NaN, NaN NaN, NaN NaN} ...)

18:29 Cr8: :missing isnt special

18:29 ,[(get {:b nil} :b :bob) (get {} :b :bob)]

18:29 Bronsa: sdegutis: I've given you at least two reasons why `=` behaves correctly with regards to nil values

18:29 clojurebot: [nil :bob]

18:29 Bronsa: which you seem to have ignored

18:31 sdegutis: Bronsa: Were your reasons about contains? and :missing?

18:31 Bronsa: read the backlog

18:31 sdegutis: Because I responded to both of those.

18:31 Cr8: ,(doc get)

18:31 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

18:32 bmay_: in Ring, how do i get the file content from a file submitted with enctype multipart/form-data

18:34 sdegutis: This is how = should be defined for maps `ms`: (every? (fn [k] (apply = (map #(get % k) ms))) (distinct (mapcat keys ms)))

18:34 Bronsa: reading now

18:34 Cr8: that would make it impossible to represent nil as a value of a kv pair in a map

18:34 why is that better

18:34 sdegutis: Cr8: how so?

18:35 Cr8: if {:b nil} and {} are equivalent then you can't safely truck {:b nil} around

18:35 sdegutis: Cr8: It makes {:a 1} indistinguishable from {:a 1, :b nil}, but for the general case that doesn't matter.

18:35 Cr8: yeah and it breaks *every case where it does*

18:35 sdegutis: Cr8: in what situation?

18:35 Cr8: say you're sticking those in a cache

18:35 you put in {:b nil} and you get back {} when you ask for it back

18:35 that's a problem

18:35 Bronsa: sdegutis: you seem to think that your general case is everybody's general case

18:36 sdegutis: A cache sounds like a highly specific problem where nil values probably have a special meaning.

18:36 Bronsa: Yep. Pretty darn sure it is.

18:36 Bronsa: good. implement your own = and use that then

18:37 sdegutis: Bronsa: I'm pretty sure you have just as little code to back up your assertion that it's not as much as you think I have to support that it is.

18:37 Cr8: thing is {:b nil} and {} are -different data-, and if = considered them the same I couldn't use huge parts of the stdlib

18:37 if i cared about it

18:37 Bronsa: i'd rather have my maps be not= when `keys` or `count` than for them to be =

18:37 Cr8: and i might not *know* if I don't care about it, i might be a library author

18:37 justin_smith: (apply merge (repeat 9 {Double/NaN Double/NaN}))

18:37 Bronsa: when `keys` or `count` are not=

18:37 justin_smith: ,(apply merge (repeat 9 {Double/NaN Double/NaN}))

18:37 clojurebot: {NaN NaN, NaN NaN, NaN NaN, NaN NaN, NaN NaN, ...}

18:37 justin_smith: ,(apply merge (repeat 10 {Double/NaN Double/NaN}))

18:37 clojurebot: {NaN NaN}

18:38 sdegutis: Cr8: I fundamentally disagree, considering almost every single time you use a map is with (get) or some variation that uses (get).

18:38 hiredman: huh

18:38 Bronsa: justin_smith: is spamming NaN your subtle way to stop a flame? :)

18:38 justin_smith: Bronsa: I found the difference between the 9 map and 10 map result amusing

18:38 Bronsa: oh wait

18:38 I didn't even notice that

18:39 Cr8: example: passing a param map to something than generates a url query string

18:39 example: serializing json to pass to some api that expects a key to be present and null

18:39 Bronsa: justin_smith: one is a PAM and the other is a PHM, but I have no idea how they can compare equal :|

18:40 Cr8: really anything that consumes an entire map, or might care about the presence of a key

18:40 Bronsa: sdegutis: I couldn't undertand your last sentence.

18:40 justin_smith: clearly they are hashing or comparing differently - probably no differences that actually matter to code that is not insane

18:42 sdegutis: Bronsa: The highest priority driving forces of a data structure is how you use it, not how it's implemented. And even then, it's how they're most often used, not the few niche situations.

18:42 Bronsa: So the most important driving features of maps are assoc, merge, and get.

18:42 Cr8: how is it useful to make it not workable to put nil in your collection

18:42 Bronsa: justin_smith: ah, it is possible that PAM doesn't use pointer identity checks while the PHM does, I guess

18:43 sdegutis: Bronsa: contains? is lower priority than these, since you usually just want to know the value of a key, not whether it's there or not.

18:43 Bronsa: sdegutis: and they are more important because you decided so?

18:43 sdegutis: what about count, keys, vals?

18:43 justin_smith: find even

18:43 Cr8: or even (seq)

18:43 sdegutis: Bronsa: Because in my 4 years of experience writing Clojure full-time professionally, this is what I have encountered in my own code, the code of my colleagues, and code I have seen written in third party libs.

18:44 Cr8: a map is a collection of kv pairs, why would you throw some out because you don't like what the .val portion is

18:44 sdegutis: Bronsa: I've rarely if ever seen count or contains? used, but sometimes keys and vals used by programmer-centric libraries.

18:44 (like a testing framework)

18:44 Bronsa: sdegutis: functions must return the *right* value not some opinionated result based on what is more generally used in your experience

18:45 sdegutis: and in your 4 years of experience writing clojure full-time professionally it just now occurs to you that (not= {:a 1} {:a 1 :b nil})? I'm sorry but if that's the case you might have some serious misunderstanding of the philosophy behind some design clojure design choices

18:46 Cr8: if you are going to argue that (= {:b nil} {}) you need to argue {:b nil} shouldn't compile

18:46 otherwise the whole type would by maddeningly inconsistent

18:47 Bronsa: justin_smith: gah now you got me curious to see if there's actually a PAM/PHM bug hidden in there

18:50 sdegutis: Bronsa: Actually no, it came up years ago, resulting in me writing a special equality function for maps for our own use.

18:51 Bronsa: But I fully agree with you, it should do /the right thing/, not some opinionated thing. And I believe the right thing is the definition I provided, and that your suggestion of it being fine the way it is is just your incorrect opinion.

18:51 sobel: how can i make string/replace match case-insensitive?

18:51 justin_smith: sobel: with a case-insensitive regex?

18:51 sdegutis: Bronsa: Because you tend to agree with rhickey simply because he's rhickey rather than to think of how functions should work.

18:51 Bronsa: sdegutis: that's insulting and ignorant

18:52 sdegutis: contains? is a stupid function and works stupidly and is stupidly named.

18:52 justin_smith: sdegutis: I've seen Bronsa complain a lot about clojure internals

18:52 sobel: justin_smith: i'm sure it's obvious when you already know how to do it

18:52 sdegutis: justin_smith: but the public-facing API is another story

18:52 justin_smith: sobel: clojure regexes are java regexes, there is a ?i key

18:52 sdegutis: contains? should work completely differently, it should tell you whether a collection contains an element

18:52 Bronsa: sdegutis: I complain about the public API just aswell

18:53 justin_smith: ,(matches #"WORD" "word")

18:53 clojurebot: #error {\n :cause "Unable to resolve symbol: matches in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: matches in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6611]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: matches i...

18:53 justin_smith: ,(re-matches #"WORD" "word")

18:53 clojurebot: nil

18:53 sobel: justin_smith: thx, think i found the relevant doc bits now

18:53 justin_smith: ,(re-matches #"?iWORD" "word")

18:53 clojurebot: #<SecurityException java.lang.SecurityException: denied>

18:54 justin_smith: ,(re-matches #"(?i)WORD" "word")

18:54 clojurebot: "word"

18:54 justin_smith: finally

18:54 Bronsa: "Dangling meta character '?' near index 0" is an awesome error message

18:55 justin_smith: Bronsa: dangling off the front, heh

18:59 Bronsa: ,(let [a (hash-map Double/NaN 1)] [(assoc a Double/NaN 2) (assoc a (key (first a)) 2)])

18:59 clojurebot: [{NaN 1, NaN 2} {NaN 2}]

18:59 Bronsa: wtf

19:00 justin_smith: wow

19:00 Bronsa: isn't that suppoosed to be impossible? I thought NaN returned false for pointer equality

19:00 hiredman: (hash Double/NAN)

19:00 ,(hash Double/NAN)

19:00 clojurebot: #error {\n :cause "Unable to find static field: NAN in class java.lang.Double"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to find static field: NAN in class java.lang.Double, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6611]}\n {:type java.lang.RuntimeException\n :message "Unable to find st...

19:01 hiredman: ,(hash Double/NaN)

19:01 clojurebot: 2146959360

19:01 hiredman: ,(hash Double/NaN)

19:01 clojurebot: 2146959360

19:01 hiredman: hmmmm

19:01 Bronsa: hiredman: yeah but they still have to compare =

19:01 hiredman: Bronsa: doesn't matter

19:01 for hash maps equality only kicks in after hashing

19:02 ,(hash (Double. Double/NaN))

19:02 clojurebot: 2146959360

19:03 hiredman: but I guess I was wrong

19:03 I assumed some kind of boxing thing created boxed NaN's with different hashes

19:03 Bronsa: uhmm

19:03 if my printlns are correct the value always gets assoc'd

19:04 hiredman: ,(let [a (hash-map (Object.) 1)] [(assoc a (Object.) 2) (assoc a (key (first a)) 2)])

19:04 clojurebot: [{#object[java.lang.Object 0x17334611 "java.lang.Object@17334611"] 1, #object[java.lang.Object 0x273d11fd "java.lang.Object@273d11fd"] 2} {#object[java.lang.Object 0x17334611 "java.lang.Object@17334611"] 2}]

19:04 Bronsa: ,(let [a (hash-map Double/NaN 1)] (identical? (assoc a Double/NaN 2) a))

19:04 clojurebot: false

19:05 hiredman: hard to see, but you get the same looking thing with objects that have identity

19:05 Bronsa: oh well obviously, the value is different mhh

19:05 uhm weird

19:06 no wait, not really?

19:06 hiredman: in the object case it's supposed to pass the pointer check

19:06 NaN is not

19:06 hiredman: sure, but in the second case it short circuits on the identity check

19:06 Bronsa: ,(let [a Double/NaN] (identical? a a))

19:06 clojurebot: false

19:07 Bronsa: ,(let [a (Object.)] (identical? a a))

19:07 clojurebot: true

19:07 hiredman: hmmm

19:07 Bronsa: like, it'd look like someplace in PHM it's using just the hashCode rather than doing equality checks

19:08 because there's no way for NaNs to compare equal or identical?, just the hash

19:16 what the

19:16 ,(let [a (hash-map Double/NaN 1)] (= (key (first a)) (key (first a))))

19:16 clojurebot: true

19:16 Bronsa: ,(let [a Double/NaN] (= a a))

19:16 clojurebot: false

19:16 hiredman: ah hah

19:17 it has to be some kind of boxing issue

19:18 ,(= (Double/valueOf Double/NaN) (Double/valueOf Double/NaN))

19:18 clojurebot: false

19:18 hiredman: ,(let [a (hash-map Double/NaN 1)] (identical? (key (first a)) (key (first a))))

19:18 clojurebot: true

19:18 Bronsa: is this some jvm weirdness I'm not aware of

19:19 hiredman: ,(let [a (hash-map Double/NaN 1)] (identical? (double (key (first a))) (double (key (first a)))))

19:19 clojurebot: false

19:19 hiredman: hah

19:19 justin_smith: ,(let [a [Double/NaN]] (= (first a) (first a)))

19:19 clojurebot: true

19:19 Bronsa: hiredman: how can you laugh, I'm having some serious identity crisis over here

19:20 hiredman: you have to laugh

19:20 floating point

19:20 ,(let [a (hash-map Double/NaN 1)] (identical? (double (key (first a))) (double (key (first a)))))

19:20 clojurebot: false

19:21 hiredman: ,(let [a (doto (java.util.HashMap.) (.add Double/NaN 1))] (= (key (first a)) (key (first a))))

19:21 clojurebot: #error {\n :cause "No matching method found: add for class java.util.HashMap"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching method found: add for class java.util.HashMap"\n :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]}]\n :trace\n [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]\n [clojure.lang.Reflector invokeInstanceMe...

19:21 hiredman: ,(let [a (doto (java.util.HashMap.) (.put Double/NaN 1))] (= (key (first a)) (key (first a))))

19:21 clojurebot: true

19:22 Bronsa: here we go

19:22 ,(let [a (Double/valueOf Double/NaN)] (identical? a a))

19:22 clojurebot: true

19:22 Bronsa: boxed NaNs compare identical

19:23 hiredman: ah, well, there you go

19:25 Bronsa: but now the question is why if they compare identical? PAM doesn't behave like PHM :P

19:27 ,(let [a (Double/valueOf Double/NaN)] (clojure.lang.Numbers/equal a a))

19:27 clojurebot: false

19:27 Bronsa: and here's the answer

19:31 looks like Numbers/equal doesn't do pointer any pointer check but just unboxes the values and compares them

19:31 ,(let [a (Double/valueOf Double/NaN)] (identical? a a))

19:31 clojurebot: true

19:31 Bronsa: ,(let [a (Double/valueOf Double/NaN)] (identical? (.doubleValue a) (.doubleValue a)))

19:31 clojurebot: false

19:32 hiredman: oh jvm

19:32 Bronsa: no idea why PAM uses Util.equivPred

19:34 well that was fun

19:38 ,(.equals Double/NaN Double/NaN)

19:38 clojurebot: true

19:38 Bronsa: TIL

19:53 elvis4526: I have troubling understanding the difference between core.match and core.unify

19:53 hiredman: unification can be two way, pattern matching tends to be one way

19:54 elvis4526: I have trouble seeing where matching the other way around could be useful

19:54 Do you have an example ?

19:54 hiredman: it is useful for various tree searching things

19:55 logic programming tends to be built on unification

19:56 so core.logic's ==

19:56 it doesn't use unify, but it has its own unifier

19:57 a unifier lets you say, I don't know what they two values are, but they are the same

19:58 elvis4526: interesting its like algebra

19:59 hiredman: exactly

19:59 some logic programming guys prefer to refer to it as relational programming

20:00 because you specify relations between things (and then maybe search for a set of things with those relations)

20:01 you often end up getting some like a unifier when implementing type inference, because you may not kow the types of terms in certain scopes, but you know how they relate

20:01 something

20:14 numberten: can you add to prismatic schemas? for ex: take the json-coercion-matcher and add a datetime coercion rule to it?

21:07 gfredericks: numberten: there's no thrown?, you just have to catch things

21:08 numberten: gfredericks: that's what I ended up doing, thanks

21:08 figured I would check to see if there was an idiomatic nicer way :)

21:08 gfredericks: numberten: and you can write your own matchers with schema, you just have to study the code they used for json-coercion-matcher; it's a bit abstract/trippy

21:08 numberten: gfredericks: haha yeah.. I ended up just doing some manual coercion

21:09 if it becomes a pattern I'll see if I can abstract it out

21:09 gfredericks: numberten: I did a custom one to do keywordization and kebabization and UUIDization and DateTimeization and I love it

21:10 numberten: yeah it seems like it would be nifty

21:11 gfredericks: numberten: as for the let-bindings question, if it's constant why not put the let outside the for-all?

21:11 numberten: i wanted it out of local scope

21:11 something inbetween file-wide private and the for-all itself

21:12 gfredericks: (let [...] (prop/for-all [...] ...))?

21:13 numberten: I didn't realize you could do that

21:13 thanks :)

21:14 gfredericks: no problem, that's what I was trying to suggest at first

21:15 numberten: ah, I see

21:48 slester: Do most Clojurists seem to use OS X for development or Linux? I'm in the market for a new laptop... and yes, it's a weird question to ask, but just curious. I see a lot of MacBooks during talks on youtube.

21:50 TEttinger: slester: I think if you're doing JVM clojure dev, OS doesn't matter that much

21:50 JVM runs pretty much the same everywhere

21:51 clojurescript some tools may be better for server-y stuff if you are using an OS that has oriented itself for that, like Linux, but I don't know how much that matters. also linux drivers are, depending on brand, sometimes not good on laptops

21:52 generally smaller not-big-name parts are slower to get drivers

21:53 as in, if your hardware contains a name that has no english translations anywhere, expect english-speaking linux devs to be slower to release support for it, heh

21:54 slester: haha

21:54 yeah, I know. I was just curious if there was a large leaning to OS X, or Windows, or *nix

21:56 TEttinger: however, if you're living in an island nation like new zealand, far away from major markets, your best bet for reasonable prices on laptops may be an online marketplace like, say, AliExpress, where many laptops are made in the same or similar factories as HP or Lenovo or whatnot but for whatever reason are unbranded with a major name

21:57 I've had surprisingly good experience buying tv sticks from AliExpress, the quality has been fine. one box came with a dead bug that had slipped in during transit, haha, but the device worked perfectly

21:58 for a long time that was the only place to buy them if they just came out

21:58 slester: I'm in the US, so that shouldn't be an issue, but ... yikes!

21:58 TEttinger: haha

21:58 yeah it was a silverfish, which seems like it slipped in on the american side

21:59 I don't know if they have the same kinds across the pacific

21:59 they eat paper and glue, bane of books

22:00 Jaood: slester: I would say most do dev in OS X and deploy to linux, they don't leave OS X because of the nice integration with hardware(macbooks) and a more polished desktop, some use linux VMs in OS X

22:00 slester: oh! silverfish aren't so bad, they're everywhere

22:00 Jaood: slester: depends on your preferences and what you are doing

22:01 TEttinger: also, reliable build quality from apple

22:01 and reliably higher prices

22:01 slester: I'm thinking just for sturdiness and dependability. My current laptop (3.5 years old now) was a 'gaming' one that feels pretty... flimsy? I don't know. It has a strange feel.

22:01 macbooks and thinkpads have the kind of solid feel I like

22:02 Jaood: slester: If I recall well lein doesn't play nice in windows

22:02 slester: I'm on linux

22:02 well I have windows 10 on a partition I only use if I need windows-specific apps

22:03 Jaood: slester: dell has some ubuntu certified laptops

22:03 TEttinger: I'm very very happy with the build quality on this MSI gaming laptop

22:03 slester: the thing I hate about my current linux setup is that switching languages/keyboards is awful

22:03 I still haven't figured out how to get it to work

22:03 OS X it's 3 clicks

22:04 atomi: slester, have you tried Cinnamon?

22:04 slester: atomi, nope, I haven't

22:04 I'm on KDE5

22:04 atomi: it's good imo

22:04 slester: I may look into it

22:04 TEttinger: I had a lenovo Y series that had just awful build quality, but once I 1) disabled the GPU by 2) installing windows server 2008 R2 as the OS, fresh install, and 2) disabled the windows audio driver because the sound card gets messed up on every lenovo it seems, it works fine. very long uptime, I use it as a server on a cooling pad.

22:05 http://www.techbargains.com/apple-macbook-pro-retina-deals#newsID441241 I have no idea if these are good deals for macs

22:05 considering there are 1/3 the price laptops elsewhere on there running win10

22:06 slester: TEttinger, I'll check that out, but yeah, even a deeply discounted macbook is way expensive

22:06 TEttinger: http://www.techbargains.com/dell-inspiron-15-deals#newsID457636

22:06 slester: plus I don't really like apple as a company

22:06 but that's neither here nor there

22:07 oh nice, they have 4k laptops :O

22:07 clojuring in so many pixels!!!

22:22 Andddd Linux just broke. Haha.

23:02 nicola: i have a list of actions to perform, each one being executed only on the success of the previous one (otherwise exit with some return message); is there an idiomatic way to write this in clojure without lots of nesting? i'm thinking something along the lines of the Maybe monad in haskell if it helps ...

23:05 johannbestowrous: you can do assertions at every action

23:05 and wrap the actions in a try catch

23:06 nicola: that would be very similar to what i'm doing right now

23:06 gfredericks: nicola: the maybe monad is a lot like some->; it's when you want the either monad that options get sparser

23:07 nicola: gfredericks: i'm not familiar with this, i'll look into it, thanks

23:08 (i mean i'm familiar with either monad in haskell, not sure about the clojure equivalent)

23:18 slester: any nice function to remove one matching value from a list?

23:18 ,'(:a :a)

23:18 for instance

23:18 clojurebot: (:a :a)

23:18 slester: to just remove one of those

23:18 johannbestowrous: you mean the first equality?

23:19 slester: Just one matching :a -- like disj but for a list, and just one element

23:19 (= (some-fn '(:a :b) :a) '(b)) and also (= (some-fn '(:a :a) :a) '(:a))

23:21 johannbestowrous: haha watch out some-fn is actually a core function just saw it today https://clojuredocs.org/clojure.core/some-fn

23:21 slester: ... whoops

23:21 haha

23:22 I meant generic function I am wanting :P

23:23 gfredericks: slester: it doesn't exist, probably because it would be inefficient for lists; e.g., should you be using a map instead?

23:26 TEttinger: ,(defn remove-first [coll] (let [sp (split-with (partial = :b) coll)] (concat (butlast (first sp)) (second sp))))

23:26 clojurebot: #'sandbox/remove-first

23:26 TEttinger: ,(let [ls '(:a :b :a :b :a)] (remove-first ls))

23:26 clojurebot: (:a :b :a :b :a)

23:27 TEttinger: damn

23:27 johannbestowrous: noice

23:27 TEttinger: not work

23:27 slester: I talk about getting a new laptop today, and then my computer crashes 3 times in a row. What'd I miss haha

23:28 TEttinger: ,(defn remove-first [coll item] (let [sp (split-with (partial not= item) coll)] (concat (butlast (first sp)) (second sp))))

23:28 clojurebot: #'sandbox/remove-first

23:28 TEttinger: ,(let [ls '(:a :b :a :b :a)] (remove-first ls :b))

23:28 clojurebot: (:b :a :b :a)

23:28 TEttinger: right.

23:28 ,(defn remove-first [coll item] (let [sp (split-with (partial not= item) coll)] (concat (first sp) (rest (second sp)))))

23:28 clojurebot: #'sandbox/remove-first

23:28 TEttinger: ,(let [ls '(:a :b :a :b :a)] (remove-first ls :b))

23:28 clojurebot: (:a :a :b :a)

23:29 TEttinger: it's highly inefficient but if you need that behavior, sure

23:29 slester: oh awesome! here's my use case, maybe there's a better way

23:29 in this game, we have a hand of 1-2 cards. cards can be duplicates.

23:30 If I want to play a knight and the hand is '(:knight :knight), it doesn't matter which one I pick, and order doesn't matter either

23:31 TEttinger: (you may want to prefer vectors over quoted lists when using clojure for a few reasons, I'll get back to that later)

23:31 gfredericks: slester: you could keep a frequency map

23:31 ,(frequencies [:knight :knight])

23:31 clojurebot: {:knight 2}

23:31 gfredericks: ^ that data structure

23:31 TEttinger: ,(frequencies [:knight :knight :dammit :gfredericks :ninja])

23:31 clojurebot: {:knight 2, :dammit 1, :gfredericks 1, :ninja 1}

23:32 TEttinger: if using frequencies, this does become easier

23:32 ,(def hand {:knight 2 :king 1 :pawn 4})

23:32 clojurebot: #'sandbox/hand

23:33 slester: how would I push a card into that?

23:33 gfredericks: (update m card-name inc)

23:33 ,(update hand :TEttinger (fnil inc 0))

23:33 clojurebot: {:knight 2, :king 1, :pawn 4, :TEttinger 1}

23:33 TEttinger: god, 1.7 helps with that stuff a lot

23:33 gfredericks: forgot the fnil

23:33 slester: I thought I was being so good and choosing the right data type but I was so wrong

23:34 TEttinger: well it's interesting

23:34 quoted lists are really common in other lisps

23:34 along with using the behavior of quoting everything inside them

23:34 johannbestowrous: https://gist.github.com/jobez/27edc10dfe867deed82f here's a remove-first

23:34 TEttinger: ,'(I love pie)

23:34 clojurebot: (I love pie)

23:35 TEttinger: but they start having trouble with nesting and when you don't actually want to quote stuff

23:35 ,'(I love (+ 1 2))

23:35 clojurebot: (I love (+ 1 2))

23:35 gfredericks: slester: related vocabulary are "multiset" and "bag"

23:36 slester: gfredericks, as in 'things clojure doesn't have'? hehe

23:36 gfredericks: no things related to frequency maps

23:37 TEttinger: vectors work very well for data that needs random access, and are otherwise similar to seqs (IIRC if you call "(list 1 2 3)" it actually runs as its body "(seq 1 2 3)"). they conj at the end instead of at the beginning for seqs.

23:39 slester: TEttinger, seems reasonable

23:39 TEttinger: a multiset is, basically, a subcategory of associative maps

23:39 it has what would be the set's items as keys, so they are still unique, but has counts for values

23:39 slester: cool, I didn't make the connection until gfredericks made that comment

23:39 :D

23:40 TEttinger: so if you have a non-strictly typed map implementation, you have multisets already, which is nice

23:40 (if you have a strictly typed one, you can do multisets for one kind of set entry)

23:40 gfredericks: you could imagine a multiset API similar to a set API instead of exposing it as a map

23:41 I'm sure there's a clojure library for this somewhere

23:41 TEttinger: flatland curates a number of useful libs, some for data structures. I love ordered collections myself, and I believe either flatland/ordered or amalloy/ordered is the most recent

23:42 I recently encountered a bizarre bug with a java demo I wrote for a gamedev lib to be used from clojure at some point

23:42 it generated the same dungeon layout in terms of walls, every time, with the same seed used every time

23:43 but on java 7, the water was in a different place than on java 8

23:43 virmundi: hello

23:43 TEttinger: I couldn't figure it out...

23:43 hey virmundi

23:43 virmundi: does anyone know how to split a string on a hex value? I have a CSV style file where the split is 0x1F

23:44 TEttinger: virmundi: the string or the char?

23:44 virmundi: within the row. Rows are new line split

23:44 the char

23:44 sdegutis: Why doesn't this work? (-> #(prn :hi) ())

23:44 TEttinger: ,(clojure.string/split "\u001F" "hey\u001Fvirmundi\u001fhow is it going?")

23:44 clojurebot: #error {\n :cause "java.lang.String cannot be cast to java.util.regex.Pattern"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to java.util.regex.Pattern"\n :at [clojure.string$split invoke "string.clj" 217]}]\n :trace\n [[clojure.string$split invoke "string.clj" 217]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compile...

23:45 TEttinger: ,(doc clojure.string/split)

23:45 clojurebot: "([s re] [s re limit]); Splits string on a regular expression. Optional argument limit is the maximum number of splits. Not lazy. Returns vector of the splits."

23:45 sdegutis: ,(-> #(prn :hi) ())

23:45 clojurebot: #error {\n :cause "Can't call nil"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6798]}\n {:type java.lang.IllegalArgumentException\n :message "Can't call nil"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6783]}]\n :t...

23:45 virmundi: Thanks. I always forget about \u

23:45 gfredericks: ,(macroexpand-1 '(-> #(prn :hi) ())

23:45 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

23:45 gfredericks: ,(macroexpand-1 '(-> #(prn :hi) ()))

23:45 clojurebot: (nil (fn* [] (prn :hi)))

23:45 TEttinger: ,(clojure.string/split "hey\u001Fvirmundi\u001fhow is it going?" #"\u001f")

23:45 clojurebot: ["hey" "virmundi" "how is it going?"]

23:45 gfredericks: sdegutis: ^

23:46 I think the simple answer is the macro wasn't written to handle that case

23:46 I rewrote -> a couple years ago, am not sure if it did anything different before

23:46 TEttinger: ,()

23:46 clojurebot: ()

23:46 sdegutis: gfredericks: oh ok

23:47 gfredericks: it's calling first on the empty list and getting nil and just going ahead with that

23:47 sdegutis: But it should in principle handle that case, right?

23:47 Like, it makes sense semantically as calling a function, right?

23:47 gfredericks: yeah you could certainly argue that

23:47 TEttinger: ,(-> #(prn :hi) (apply))

23:47 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/apply"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/apply"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 412]\n [sandbox$eval188 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang....

23:47 sdegutis: Okay.

23:47 gfredericks: I think deliver might work

23:47 TEttinger: ,(-> #(prn :hi) (apply ()))

23:47 clojurebot: :hi\n

23:47 gfredericks: ,(-> #(prn :hi) (deliver))

23:47 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/deliver"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/deliver"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval240 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Com...

23:48 gfredericks: oh right

23:48 only for one-arg functions

23:48 TEttinger: TEttinger solved a weird thing! I'm happy

23:48 sdegutis: Although then again, the guiding purpose I have for wanting that probably doesn't extend very far beyond this one thing, and probably breaks more assumptions than it wins.

23:48 TEttinger: hahaha

23:48 TEttinger: and it works, which is kinda crazy.

23:49 virmundi: hanks

23:49 thanks

23:50 gfredericks: consarnit I think I found another bug in goog.math.Integer

23:50 sdegutis: ,(-> #(prn :hi) (apply))

23:50 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/apply"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/apply"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 412]\n [sandbox$eval266 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang....

23:51 sdegutis: Clojure is closer to Common Lisp than Haskell.

23:51 :'(

23:54 scriptor: sdegutis: because it doesn't have function currying?

23:55 that's because they chose to favor multi-arity function definitions

23:55 sdegutis: scriptor: sorry that's not what I meant

23:56 I meant, because Clojure favors exposing low-level implementation details as public APIs rather than high-level abstractions

23:56 Many functions in clojure.core are designed the way they are because efficiency and speed are considered more important than abstraction and purity to the Clojure team

23:56 By purity I don't mean in the FP sense, I meant in the cleanliness sense.

23:57 scriptor: can you give an example of low-level implementation leaking through the public API?

Logging service provided by n01se.net