#clojure log - Apr 14 2013

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

0:01 mynomoto: carlw2: https://www.refheap.com/paste/13605

0:01 carlw2: thanks

0:02 cool

0:02 thanks for that

0:02 good to know that im close

0:03 mynomoto: carlw2: https://www.refheap.com/paste/13606

0:04 carlw2: My lobos.config and lobos.migrations. That will set you up.

0:06 carlw2: perfect, im going to switch this over

0:06 thanks so much for your help

0:06 mynomoto: you're welcome.

0:46 carlw2: does anyone have any thoughts on how to mock external services for tests?

0:59 mthvedt: it seems like defmulti custom hierarchies have to be passed as vars. is this true? and if so why isn't it documented?

2:01 tyler_: how do i get more decimal places on a java.util.Date inst?

2:07 with the 3 decimal places it possible to get a duplicate inst string for different instances of state in my app

2:07 it's*

2:09 tomoj: you can't get more decimal places on a Date

2:09 tyler_: is there another way to generate an inst string in clojure besides Date?

2:10 i guess theres joda time

2:10 never really played with that

2:11 tomoj: &(java.sql.Timestamp. 0)

2:11 lazybot: ⇒ #inst "1970-01-01T00:00:00.000000000-00:00"

2:12 tyler_: woo 9 places

2:12 nice

2:12 ah nanosecond

2:13 almost enough to show hyperfine groundstate transition

2:13 tomoj: you need to change the handler for 'inst maybe if you want that

2:14 Apage43: ,(class #inst "1970-01-01T00:00:00.000000000-00:00")

2:14 clojurebot: #<SecurityException java.lang.SecurityException: denied>

2:14 tyler_: says Date

2:14 Apage43: yeah, it gets truncated to a Date by default

2:16 tomoj: (binding [*data-readers* {'inst clojure.instant/read-instant-timestamp}] (read-string #inst...))

2:16 tyler_: with all the emphasis on identity and time in the language, its kinda odd that the default implementation of time is so limited

2:32 muhoo: that's java

3:13 devn: tyler_: check out clj-time

3:14 tyler_: emphasis on time doesn't mean a robust system for inspecting representing time with strings

3:15 tyler_: it's kind of fitting really

3:15 tyler_: not technically

3:15 i meant odd from a cultural standpoint

3:17 i would have guessed that people would want time to be modeled as accurately as possible given the mindset of the people doing the program

3:17 programming*

3:18 * tyler_ has been reading too much whitehead

3:25 devn: tyler_: i dont think that's accurate

3:26 tyler_: i don't think its falsifiable conjecture

3:26 devn: tyler_: dealing with time in a way that is "automatic", like regular time is, means not thinking constantly about it

3:26 which means not managing locks

3:26 the order of things, etc.

3:27 tyler_: i just think i took away something completely different from reading whitehead

3:27 which is totally unsurprising and a little ironic

3:27 tyler_: its the beauty of philosophy

3:27 ;)

3:28 devn: i feel like whitehead trolls himself in part I

3:28 like he's setting up this impossible standard which he will eventually bow to

3:28 tyler_: by part 1 i assume you're referring to process and reality and not pricipia mathematica

3:28 devn: yeah

3:29 every sentence in that book is open to interpretation

3:30 specifically the sentences about precise language

3:31 tyler_: i think its awesome that part one has "scheme" in the title ;)

3:31 devn: heh i never noticed that

3:32 likewise, though, i think what i liked is that it all seemed so related to programming, but it was conceived at a time when all of what we know now was a figment of the imagination

3:33 tyler_: i would say that programming''s goal is to try to simulate reality, so i don't find it entirely surprising

3:33 devn: I think that's partly a lie

3:34 In civil engineering you have real physical things to worry about, like wind, for instance.

3:34 tyler_: i mean as far as lisp is concerned, in relation to its AI history

3:34 devn: With respect to programming, those are things you *invent*.

3:34 Constraints are an invention.

4:56 augustl: is it possible that leiningen loads another version of a dependency than the one I've specified when I tell it to use a specific version, such as "[0.7.1]"?

4:56 I'm getting an exception that I can't even find when grepping the source of version I depend on.. But the exception is there in older versions

4:59 "lein deps" doesn't print anything either. Never used it before, but isn't that a bit weird? It just hangs for a few seconds and then exits with no output

5:00 noidi: augustl, try lein deps :tree

5:01 plain `lein deps` is deprecated, it was used in Leiningen 1 to download dependencies (they are now downloaded automatically)

5:02 augustl: my dependency with the correct version (clj-http "0.7.1") is listed in "lein deps :tree". Not sure how to best figure out which version of the jar leiningen actually loads.. I'm pretty sure I wouldn't get this error if leiningen loaded 0.7.1

5:02 the line numbers doesn't match up in the stack trace, etc

5:02 it could also be that the git tag in clj-http for 0.7.1 is wrong, but that seems unlikely

5:03 noidi: you can use `lein classpath` to see the jars it puts on the classpath

5:03 augustl: checking the actual jar file in ~/.m2 now, it seems identical to the git repo

5:03 noidi: ah, thanks

5:05 the correct .jar is in "lein classpath" too.. I guess something else must be wrong, then.. It's deleting code until error goes away to figure out what the problem is time! :)

5:07 if anyone got some general suggestions for how to debug stack traces that contains references to source code that isn't present in "lein classpath" I'm all ears :)

5:07 noidi: how you tried turning the REPL process off and on again? :) https://www.youtube.com/watch?v=PtXtIivRRKQ

5:08 s/how/have/

5:08 andyfingerhut: Have you tried unzipping the .jar in the lein classpath and looking at the source code in there?

5:09 You could diff that against the version that you checked out with a git tag for version 0.7.1, and see if they match or not.

5:09 augustl: noidi: :)

5:09 andyfingerhut: yeah I've looked inside the jar that is on the classpath

5:09 (according to lein classpath)

5:10 andyfingerhut: I'd ask for a full refund on your Leiningen purchase price. Heck, triple for pain and suffering :-)

5:12 augustl: totally!

5:12 andyfingerhut: ~refund

5:12 clojurebot: Cool story bro.

5:13 andyfingerhut: Anyone know the incantation to teach Clojurebot to say something in response to a word or phrase?

5:14 augustl: where could leiningen possibly load a jar from other than ~/.m2?

5:14 I deleted the older versions of clj-http I had from .m2 and the stack trace still refers to line numbers that doesn't match with the only .jar of clj-http I have in ~/.m2 ...

5:18 perhaps cosmic radiation

5:18 I'll try opening a window and unplugging my phone from the charger

5:24 andyfingerhut: Which version of Leiningen are you using? 2.x I hope?

5:25 You could try deleting your entire ~/.m2 (or renaming it) and trying again.

5:32 augustl: andyfingerhut: yeah, 2.x

5:33 andyfingerhut: I only asked about the Leiningen version since the now-fairly-old 1.x versions copied .jar files into the project directory itself. 2.x doesn't.

5:35 augustl: ah, I see

5:36 something somewhere caused clj-http 0.5.3 to be downloaded.. So that's a start I guess

5:36 andyfingerhut: Does clj-http 0.5.3 show up in the output of "lein deps :tree" anywhere?

5:38 augustl: it does not

5:39 I also see that my ~/.m2 only has the pom for 0.5.3, only 0.7.1 has a .jar in it

5:39 so it seems that ~/.m2 is not where the old version is loaded from

5:45 well this is interesting. I'm manually poking around in the .jar file (it mostly contains .clj files) and that causes weird compilation errors when booting my leiningen project with "lein ring server"

5:46 the .jar file in ~/.m2 for clj-http 0.7.1 that is

5:46 andyfingerhut: Are you sure it is clj-http that produces the stack trace lines you are seeing, and not some other library?

5:46 e.g. clj-http-lite?

5:47 augustl: not sure, but the first line in the stack trace I'm getting says "client.clj:232 clj-http.client/wrap-input-coercion[fn]"

5:47 then "client.clj:151 clj-http.client/wrap-output-coercion[fn]", etc. All lines which doesn't have those functions in them in the actual jar :)

5:50 andyfingerhut: There are functions with those names in that source file in clj-http 0.7.1

5:50 augustl: I wonder why poking around in the .jar file causes exceptions like "Caused by: java.lang.RuntimeException: No such var: util/lower-case-keys" though. Where util/lower-case-keys is referenced in a file inside the .jar I just added a comment to and saved (via emacs, which supports editing inside zip files)

5:50 andyfingerhut: Not at those line numbers, agreed, but maybe you should go by the function names for now and assume the line numbers are horked?

5:50 augustl: my clj-http 0.7.1 jar has a comment string for the function wrap-redirects on line 151

5:50 hmm

5:51 I suppose I can, since I've no idea what's going on anyway :)

5:52 the line numbers doesn't match with clj-http 0.5.3 either anyways..

5:53 andyfingerhut: Are you poking around inside a .jar file while it is in use by a JVM? That doesn't sound like a recipe for reproducible behavior to me.

5:54 augustl: no, I'm restarting the jvm

5:55 or, I'm not able to start the JVM, since I get that exception when I try to start my app after poking around in the jar

6:00 MikeSeth: hmmm, my python nrepl client is almost working

6:01 soon y'all can have a working clojure repl in Sublime

6:03 augustl: got rid of my "checkouts" symlinks, so that wasn't causing oddities either

6:09 perhaps the jar has been installed on some kind of "system" classpath - does the JVM have such a thing?

6:19 ran a "find", can't find any clj-http outside of ~/.m2

6:28 perhaps versions on OS X is doing this.. </randomguess>

6:34 mpenet: use lein classpath

6:34 you might find it there

6:36 or in your situation: "lein classpath | grep clj-http"

6:37 augustl: mpenet: it's there, but my problem is that it seems that something somewhere somehow loads a completely different version

6:38 are there any generic debuggers I could attach to my running clojure process?

6:39 mpenet: ritz I guess, but I am not sure how stable it is. I think CCW has something like that too

6:42 oh btw, did you "lean clean" first? I had a similar issue after an update of a dependency where old compiled files would put me in a weird state

6:43 augustl: I did a "rm -rf target".. I'll try the "lein clean" too

6:43 "lein clean" did not help either

6:43 mpenet: :(

6:49 augustl: are there any generic debuggers for the JVM I could use?

6:49 all I really want to do is to attach a debugger to my java process and break on exceptions

8:47 cldwalker: hi, any recommendations for a mocking library seeing that clojure.contrib.mock didn't get ported over?

8:47 Ember-: alter-var-root or midje

8:49 cldwalker: I see https://github.com/EchoTeam/clj-mock but they haven't coordinated with http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

9:11 bttf: where can i find all my libs that lein pulls down?

9:11 im trying to take a look at some code for a library but i have no idea where it's located

9:14 noidi: bttf, lein classpath

9:15 katratxo: bttf: check ~/.m2/

9:16 bttf: ok

9:17 katratxo: "jars can be referenced directly out of the ~/.m2/repository directory." https://github.com/technomancy/leiningen/blob/stable/doc/FAQ.md

9:18 naeg: what's the best way to get the index of the highest number in a vector? e.g. [1 5 4 3 2] => 1

9:23 hyPiRion: ,(->> [1 5 4 3 2] (map-indexed vector) (apply max-key second) first)

9:23 clojurebot: 1

9:24 hyPiRion: It's possibly not the best way though

9:24 naeg: only found similar solutions on the net

9:24 thanks

9:25 it's just a vector of constant size 7 anyway, so not that problematic

9:47 jakzale: Hi, I have a question regarding using vars in clojure or any global mutable state. May anyone explain the usage of set! special form or point me towards a site with it. I tried googling it, but I could not find anything useful.

10:26 noidi: jakzale, you most likely don't want to use vars to hold mutable state. AFAIK their purpose is to allow interactive development by redefining functions and "constants" on the fly.

10:28 vars are for the state of your program's definitions, and the various ref types are for the state that the program itself modifies

10:29 jakzale: noidi: Ok, also, in the meantime I believe I found what I was looking for: use binding for function local mutable state.

10:30 noidi: why does your function need local mutable state? :)

10:30 clojure has excellent facilities for writing purely functional code

10:32 ravster: hello all

10:33 jakzale: i think what I was actually looking for are monads, because keeping the state in functions can get quite messy

11:19 llll: ,,:a

11:19 clojurebot: :a

11:19 llll: ,:a

11:19 clojurebot: :a

11:19 llll: ,:m/7

11:19 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :m/7>

11:19 llll: ,:7

11:19 clojurebot: :7

11:19 llll: why is that?

11:20 kmicu: , (keyword 7)

11:20 clojurebot: nil

11:20 kmicu: , (keyword '7)

11:20 clojurebot: nil

11:22 llll: ,(keyword :m/7)

11:22 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :m/7>

11:23 bbloom: ,(keyword "7")

11:23 clojurebot: :7

11:23 kmicu: , (class :7)

11:23 clojurebot: clojure.lang.Keyword

11:23 bbloom: ,(keyword "m" "7")

11:23 clojurebot: :m/7

11:23 bbloom: :m/7

11:24 ,:m/7

11:24 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :m/7>

11:24 bbloom: yup

11:24 the keyword & symbol functions don't validate their inputs all that well

11:24 nils_: hi. is there a way to get the code of a specific multimethod implementation via source?

11:25 llll: its a bug?

11:50 shriphani: Hello everyone. I am trying to parse a very simple xml string: (xml/parse "<TIMEX3 tid="t2" type="TIME" value="2005-04-12T10:30">Apr 12 10:30am 2005</TIMEX3>") and this happens: NumberFormatException Invalid number: 2005-04-12T10:30 clojure.lang.LispReader.readNumber (LispReader.java:253) . Is there anything I am missing? Why should value be bound to a number ?

11:52 borkdude: any great recent examples of clojure commercially used?

11:53 shriphani: borkdude: prismatic has a few clojure repos : https://github.com/Prismatic

11:54 borkdude: shriphani tnx

11:56 babilen: borkdude: worldsingles pops into my mind

12:00 shriphani: also nvm about my question. just me being a super-idiot.

12:03 kmicu: Najs.

12:12 shriphani: does anyone here use clojure as a scripting language ?

12:16 giacecco: borkdude: http://www.quora.com/Whos-using-Clojure-in-production

12:17 borkdude: giacecco wow, nice

12:18 giacecco: borkdude: pity the list is not accompanied by some kind of description of what they do with it, and what's the source

12:44 ravster: how do I make a 'map' call not be lazy?

12:45 I should be having 587 objects but I'm only getting 64 :(

12:45 mefesto: ravster: you could wrap the call in a doall

12:45 ,(doall (map inc (range 10)))

12:45 shriphani: hi. I have a java class of the form : public class A { public static class B() … }. I have imported A but I cannot seem to get B using either A/B or A$B. What am I doing wrong ?

12:45 clojurebot: (1 2 3 4 5 ...)

12:46 ravster: mefesto: oh, thanks

12:47 mefesto: shriphani: did you explicitly import the static inner class as well?

12:47 shriphani: mefesto: no

12:47 mefesto: shriphani: i *think* that is necessary

12:47 shriphani: I only have imported the outer class.

12:48 umm so how does the import statement look ?

12:48 mefesto: (import '[myapp A A$B])

12:48 shriphani: ah.

12:48 and I use A$B as the symbol ?

12:48 mefesto: yea

12:48 shriphani: ok.

12:48 thanks.

12:49 also. is there a way to make the repl reload everything?

12:49 Ctrl-D and lien repl always is quite painful.

12:49 lein *

12:51 mefesto: another question. I need access to B.class (this is what I have in my java code). I tried (. A$B class) but clojure says there is no class field. What is the workaround for this ?

12:52 mefesto: shriphani: doesn't A$B resolve as a class?

12:52 tomoj: :)

12:54 shriphani: mefesto: yeah that worked. Sorry I am just converting some sample code someone wrote for a wonky library in java to clojure and I am bad at both so ..

13:35 naeg: hey, wrote a connect four game with a basic minimax ai in clojure and would appreciate any feedback: https://github.com/naeg/clj-connect-four/tree/master/src/clj_connect_four

13:36 specifically about everything related to clojure, since I'm a newcomer (coding style, simplifications, ...)

13:49 chessguy: i think i have some fundamental misunderstanding of clojure.core.unify

13:49 ,(unifier 'foo 'bar)

13:49 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: unifier in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:50 chessguy: well, this returns bar for some reason. i would expect it to return nil, because they don't math

13:50 *match

13:55 shriphani: Hi. In python I could do: a,b,c = split("a b c") and have the valued bind. How do I do this inside a clojure let ?

13:55 gfredericks: shriphani: destructuring

13:56 shriphani: gfredericks: link ?

13:56 gfredericks: (let [[a b c] (something that returns a seq of three things)] ...)

13:56 $google clojure destructuring

13:56 lazybot: [Jay Fields' Thoughts: Clojure: Destructuring] http://blog.jayfields.com/2010/07/clojure-destructuring.html

13:56 shriphani: hmm and that won't work in a binding ?

13:56 gfredericks: binding like for dynamic vars?

13:57 shriphani: yea maybe like : (binding [[a,b,c] [1,2,3]] a)

13:57 (binding [[a b c] [1 2 3]] a) gives me clojure.lang.PersistentVector cannot be cast to clojure.lang.Symbol

13:58 gfredericks: right binding doesn't support that

13:58 you want to dynamically bind three vars at once?

13:58 shriphani: gfredericks: is that wrong ?

13:59 Bronsa: I don't see much sense in that.

13:59 gfredericks: I think most people don't use dynamic vars that heavily

13:59 Bronsa: also, let creates lexical bindings, binding only binds them

13:59 chessguy: sorry, i had to reboot, not sure if anyone responded to my comment about unifier

13:59 gfredericks: they tend to be for orthogonal configuration purposes

13:59 Bronsa: destructuring is usually used when creating binding

14:00 bindings*

14:00 dnolen: chessguy: just seems like a bug

14:01 chessguy: dnolen: well, it seems to be consistent.

14:01 dnolen: chessguy: core.logic's unifier returns nil for that case, those two terms don't unify.

14:01 rationalrevolt: can someone help me understand why refs have associated history? I'm trying to read through refs from the book "Clojure Programming", and it mentions: In the case of reference types, deref is guaranteed to never block. However, inside a transaction dereferencing a ref may trigger a transaction retry!

14:02 chessguy: dnolen: hmm, maybe that's what i went then

14:02 noidi: rationalrevolt, they're needed so that clojure can provide your transaction with a consistent snapshot of the world, even though some of the refs' values change during it

14:03 chessguy: here's another example: (unifier '(foo ?x) '(bar baz)) => (bar baz)

14:03 rationalrevolt: but, isn't the existence of ensure leave that to the programmers choice?

14:04 noidi: rationalrevolt, i.e. with refs a, b, c, even if the value of b changes from b1 to b2 during the transaction, clojure can still provide you with a snapshot containing [a1, b1, c1], because b1 is kept in the history

14:04 chessguy: makes me wonder if the core.unify unifier is trying to do something different

14:05 rationalrevolt: noidi: thanks, that helped

14:07 chessguy: dnolen: so the equivalent of my last example in core logic is something like this? (run* [x] (== '(foo x) '(bar baz)))

14:11 dnolen: chessguy: yeah I'm not sure what core.unify unifier is supposed to do. Probably worth asking on the ML. fwiw, unify and unifier in core.logic do the opposite of core.unify. unify returns the unified term, unifier returns the most general unifier (a substitution)

14:12 chessguy: that's not quite right. (run* [x] (== (list 'foo x) '(bar baz))), which will fail.

14:15 chessguy: dnolen: err, why do i need "list" there?

14:15 dnolen: chessguy: also, the actual core.logic translation would be (unify '[(foo ?x) (bar bbaz)])

14:15 chessguy: oh, i like that better

14:15 dnolen: chessguy: you quoted the list, x won't refer to the logic var.

14:16 chessguy: dnolen: oh, silly me, of course. thanks

14:21 berdario: Uhm, since people are talking about core.logic, can someone look at this? http://cljbin.com/paste/516af389e4b0497d9e99b008

14:22 it's the first code I've ever written with core.logic... and so there might be some obvious refactoring to be done

14:22 chessguy: dnolen: the translation you gives me results in an arity exception

14:23 berdario: so, any suggestion is welcome...

14:23 chessguy: s/gives/gave/

14:23 berdario: uh, dnolen is gone :/

14:24 chessguy: bummer

14:43 iamdrw: Hi everybody. Does anybody knows how to attach meta-data to a deftype and later retrieve it. I do (deftype ^{:meta :data} Foo []) , but (meta Foo) returns nil :-(

14:46 bbloom: iamdrw: (= (class Foo) java.lang.Class)

14:46 and Class doesn't implement IMeta

14:46 also, there is no #'user.Foo var that is created, so that won't have the meta

14:46 i'm not sure if there is anything for that metadata to be hung on

14:47 what are you trying to accomplish, maybe we can suggest an alternative

14:47 iamdrw: oh, I see

14:53 I'm trying to create a simple plugin system — I have a plugin protocol and a macro(that does deftype and extend-type) for creating such plugins. And what do I want is to have some static meta-data about this type of plugin, because current implementation has a method in protocol, which is bad — as I have to actually create a plugin in order to have meta-data. Which is confusing :)

14:58 ravster: hey all, I'm not able to understand why my code is failing at the 64th element of a list <---- https://gist.github.com/ravster/5383799

14:58 well, 65th.

14:58 but when I run the code on the 65th object, it doesn't return any errors.

14:58 just some strange stringreader thing when its inside the map

14:59 ucb: ravster: it's difficult to say without looking at the data. The number 64/5 may come from the fact that maps are realized in chunks of 32 items

14:59 ravster: ucb: what do you mean by 'realized'?

14:59 I've tried a (doall ) around the map, bt that doesn't make a difference

15:00 ucb: ravster: you know how maps are lazy? well, they're kind of lazy in that when you create one the first 32 items are realized. Forinstance, (map (fn [i] (println i)) (range 128)) shouldn't print anything, right? yet it prints numbers till 32

15:00 (or 31, haven't tested the code)

15:01 ravster: it prints all the way to 127 for me.

15:01 ucb: in the repl, sure

15:01 try wrapping that in a def

15:01 ravster: but it is in chunks of 32

15:02 ucb: e.g. (def not-so-lazy (map ...))

15:02 ravster: oh okay

15:02 ucb: so, in any case, without looking at your data i can't really tell why it may be failing on the 65th item :)

15:04 ravster: gist updated https://gist.github.com/ravster/5383799

15:04 with data

15:04 its plain json parsed and generated with cheshire.core

15:06 ucb: looks like not all items are the same shape?

15:07 ravster: oh, so it could be that 65-97 might have a problem? Not just the 65th one?

15:08 ucb: perhaps

15:09 the first few items don't seem to have the same shape

15:09 it's also difficult to see items 65- in that gist too ;)

15:09 ravster: ucb yeah :)

15:14 yay, manual binary split-search!

15:29 ucb: ravster: you found it?

15:30 ravster: yeah, its failing around 92

15:31 ucb: ravster: any thoughts why?

15:32 ravster: no clue yet. All the keys seem valid. I need to look at the ones around it.

15:37 yay. found out!

15:38 some of the data doesn't have lat and longitude! They just don't exist on the planet earth! And naturally my code didn't check for extraterrestrial schools

15:38 thanks for the 32-sets map thing hint, ucb .

15:46 adrian`: Hello all... I'm looking for advice about how to properly reason about and/or manage state for a multiplayer board game, like Chess.

15:52 chessguy: adrian`: what is your question, exactly?

15:53 adrian`: your first line of defense in clojure is usually to use pure functions on some built-in data-structure, like, in this case, a map of pieces to squares, maybe

15:55 adrian`: So I've done that for the game board/positions

15:55 oskarth: appropriate nickname :p

15:56 adrian`: but I suppose my problem is ... I have no idea how to properly syncronize state between the client (the player) & server (the "AI")

15:57 That is, without including the entire board in every call between the client/server

15:57 I'd like to just transport the move in a message to be rendered by the UI

15:58 chessguy: so do that then

15:58 naeg: what should one use to handle command line args?

15:58 chessguy: by the way, most serious UIs don't re-invent a UI

15:59 adrian`: If the goal were to just render the moves, then that would sufficient

16:00 But the reason I'm doing this is because I thought taking a functional approach to AI would be interesting and a good learning experience, but I'm having trouble mapping the actual backend stateful logic into a functional domain

16:01 chessguy: adrian`: "backend stateful logic"? you mean drawing the UI?

16:02 adrian`: no, I mean the decision making for the AI's move

16:02 chessguy: adrian`: ah. have you read the famous "why functional programming matters" paper?

16:03 adrian`: has a nice, long example of doing tree search in a functional style

16:03 adrian`: in order to make good moves the AI needs to maintain state of the game between moves, like positional data, zobrist keys etc.

16:03 I haven't

16:04 I'll check it out

16:05 chessguy: adrian`: definitely worth a read, though i haven't seen it translated to a modern engine with thinks like hash tables like you're describing

16:06 *things

16:06 adrian`: But I should mention that my issue is not reasoning about the structure of the data from a functional perspective, (I think I have a decent grasp on that end) but rather about how to syncronize state between asyncronous agents in a proper "functional way"

16:07 chessguy: adrian`: why do the agents need to be asynchronous?

16:07 adrian`: By that I mean, if the entire game were encapsulated in a single function I wouldn't be having the problem

16:07 The AI has to respond to a player's move, which then has to be syncronized

16:07 but I don't want it to block

16:07 What if the server is playing two players, for example?

16:08 It has to be able to dispatch the move to the right game for processing

16:09 but I can't think of a way to do that without recreating the entire state of the game every time, which would mean the transport data would be huge

16:13 chessguy: adrian`: well, i haven't played a lot with clojure concurrency yet, but what happens when you have multiple agents where the state is a board?

16:15 adrian`: I'm not sure what you mean

16:16 chessguy: have you tried applying clojure agents (http://clojure.org/agents) to the problem?

16:17 adrian`: I have, but I'm having issues most likely due to my general ignorance about how to properly reason Clojure's way of handling state

16:19 I have yet to find a good resource for working with agents/refs/atoms when dealing with data that is more "abstraction" oriented than primitive types

16:21 Like, for example, let's say I want to have the game be an agent - any idea how to properly have the agent inherit the datatypes already implemented interfaces?

16:22 Like if I have a protocol to model some chess playing intelligence - it has a board, a piece color, available moves set, a move history etc.

16:23 I mean, a record

16:23 iamdrw: member:adrian%60 (def board (atom {})

16:23 adrian`: Now that record implements some protocol

16:24 How do I create an agent/ref/atom that when instantiated has the records protocol methods already implemented?

16:24 @iamdrw That's a map

16:25 What if the data is a record with lots of predefined structure, methods

16:25 and it implements arbitrary protocols

16:25 iamdrw: why not use map inside defrecord?

16:26 adrian`: I mean, the move history is a map

16:27 but other things are not easily represented by a map... like the zobrist hashes, they're an array of bitsets which are arranged in a way to reduce repetitive computation, and that's a necessary field of the game board for the AI to use

16:27 That's just one field

16:28 chessguy: adrian`: can't that be one value in the overall map though?

16:28 adrian`: Well, records are basically maps

16:29 but when you just define vars like (def board (Board. (atom (new-board))))

16:30 since the board is a type being created as an atom, the atomic structure hasn't implemented the protocols of the Board type

16:30 iamdrw: if you are able to implement zobrist hashes in clojure vector/maps then you could use all clojure concurency — atoms, refs, agents, promises, futures and so on.

16:32 but they are different — as maps are functions

16:32 adrian`: So basically I should refactor everything out of protocols/records into maps/vectors?

16:32 iamdrw: and record — is a java class

16:32 I guess you should find a balance between using your defined types and standard maps/vectors

16:34 adrian`: I guess I could do that

16:34 iamdrw: and also you could check the 11th chapter of Joy Of Clojure — for more info about clojure concurrency model

16:34 adrian`: Although I like the abstraction

16:39 iamdrw: you could use the abstraction and use clojure map or vector of changes encapsulated inside record.

18:24 _Vi: On [this page](http://clojuredocs.org/clojure_core/1.2.0/clojure.core/*print-dup*) I see "serialize" and "deserialize" functions which use "read". But unlike in the documentation for "read", here there is no warning about "Don't deserialise untrusted data". I have just found those functions being used in my project...

18:28 How to read with clojure.edn/read-string the data which was previously saved with that "serialize"? It begins with "#=(clojure.lang.PersistentArrayMap/create".

18:32 bbloom: _Vi: sorta the point of clojure.edn/read-string is that it can't read #= forms

18:32 _Vi: if you trust the data is not malicious, then you can just use clojure.core/read-string

18:33 _Vi: bbloom, The data is stored on remote server. I was thinking "I'm using official serialisation routing copied from official docs)" and only now found out that it is simple "read".

18:33 s/routing/routine/

18:35 Now I want to switch to EDN, but also want to be able to read old files. Is just stripping away that #=(clojure.lang.PersistentArrayMap/create enough to correctly read that? (it's a simple map of maps of various keywords and strings).

18:35 Now I want to switch to EDN, but also want to be able to read old files. Is just stripping away that #=(clojure.lang.PersistentArrayMap/create enough to correctly read that? (it's a simple map of maps of various keywords and strings and numbers).

18:36 bbloom: _Vi: #= implies you set *print-dup* to true, which must have been done for a reason... but regardless of the reason, the simplest thing to do is to port your data via clojure.core/read and then clojure.edn/pr

18:37 _Vi: if porting the data in bulk is not an option, you'll need to get creative

18:37 _Vi: Is simple data (without custom classes or such) saved with *print-dup* fundamentally different that data saved without *print-dup*?

18:38 bbloom: depends on what you mean by fundamentally :-P in short: print-dup prints text that is NOT EDN, it is Clojure Forms, which is a superset

18:38 it's also an UNSAFE superset

18:39 _Vi: think of it as eval vs JSON.parse

18:42 _Vi: For my case it looks like if I just remove the beginning ("#=(clojure.lang.PersistentArrayMap/create ") and the end (")\n") clojure.edn/read-string successfully reads the thing.

18:43 bbloom: _Vi: like i said, you can get creative

18:43 _Vi: just ask my good buddies sed and awk

18:44 _Vi: But the page about *print-dup* should be edited, I think...

18:44 It should say: 1. deserialize is insecure for untrusted, 2. consider EDN, 3. it is not compatible with EDN...

18:45 bbloom: _Vi: EDN is very new & documentation moves slowly :-/

18:48 dnolen: chessguy: re unify translation earlier - works for me.

18:50 pretty neat use of clojure.core.logic.fd http://github.com/namin/metasolfeggio/commit/0dcc51d7678b423984967e6b2147e6bbeb139339#comments, counterpoint via overtone

18:50 brehaut: bbloom: quite a euphemism

18:52 _Vi: BTW: is there a simple way to "prn" an object with identation. I'm not looking for big and slow pprint, just serialize data in _slightly_ nicer than one long line format?

18:52 bbloom: _Vi: who says pprinting has to be slow?! https://github.com/brandonbloom/fipp :-)

18:53 _Vi: fipp is also slow: I've checked (fipp was suggested at StackOverflow).

18:53 chessguy: dnolen: i'm doing something wrong then. i have (ns foo (:require [clojure.core.logic.unifier :as logic])), followed by (logic/unifier '(?x ?y ?z) '(1 2 ?y))

18:53 bbloom: _Vi: aw :-( bummer (i wrote fipp) there are plenty of opportunities for optimizing it

18:53 _Vi: (time (do (with-out-str (fipp (repeat 1000 [{:q 3 :d 4} 5]))) nil))

18:53 "Elapsed time: 8945.981596 msecs"

18:54 bbloom: _Vi: yeah, you can definitely beat the pants of fipp with a brain dead indenter

18:54 chessguy: dnolen: err, that's not exactly what you gave me, but i was playing with it a bit trying to get it working

18:54 _Vi: Just prn is 132 msecs.

18:55 bbloom: _Vi: what do you get with clojure's pprint ?

18:55 _Vi: Now using hacky way: (-> object prn-str (clojure.string/replace " {" "\n{") (clojure.string/replace ", " ",\n")). It more or less suits the task, but not a generic solution.

18:56 Now measuring.... Waiting...

18:56 "Elapsed time: 17216.384673 msecs"

18:56 bbloom: yeah, about twice fipp is what i was seeing

18:56 i can probably make fipp a lot lot faster

18:56 it does a boatload of allocating right now

18:57 _Vi: Maybe fipp should have a "simple mode" for serializing big chunks of data?

18:57 I expect indented output to be, for instance, 20%-30% slower than regular... But not 2 or 3 times slower...

18:58 dnolen: chessguy: yes that is not correct, unifier takes vector of terms, it does not take a terms as individual arguments.

18:58 bbloom: a "simple mode" is unlikely to be where i'd start, since i suspect (although have not proven) that the perf hit comes from all the intermediate structures, not the measuring process

18:59 _Vi: Does fipp always print the same as prn (except of formatting)? No chance it breaks any data compared to prn?

19:01 bbloom: _Vi: fipp only has a couple of people using it (that i've heard from), but i haven't gotten any bug reports on the EDN correctness

19:01 _Vi: that's about as confidently as i can answer that question

19:02 ravster: I'm trying to do a case on (type foo), and its not accepting clojure.lang.PersistentArrayMap

19:02 _Vi: BTW we have clojure.edn/read-string. Maybe there should be also clojure.edn/write-string. Even if it does the same as pr-str, it can be beneficial to have symmetry...

19:03 ravster: the exception I'm having it throw is returning "class clojure.lang.PersistentArrayMap" instead

19:03 bbloom: _Vi: that's a suggestion for the mailing list & may be best accompanied by a ticket/patch

19:04 ravster: hmm, maybe thats something that happens when I do (str (type foo)) in the exception. But still it shouldn't get to that point

19:04 _Vi: Does the mailing list support sending without being subscribed to it? Or just open a JIRA ticket?

19:05 bbloom: _Vi: you can join the google group w/o signing up for a email subscription

19:05 _Vi: well, that's the clojure users group, if you want to join the clojure dev group, you need a signed contributor agreement

19:06 amalloy: ravster: case doesn't evaluate its test clauses. clojure.lang.PersistentArrayMap is a symbol, not a class; when evluated, it produces a class

19:08 ravster: So (type foo) creates a class?

19:08 _Vi: Strange... My dev.clojure.org user account no longer works (and email is "forgotten" also).

19:09 dnolen: ravster: case only works on compile time literals, I don't think you can make it work on classes.

19:09 ravster: okay

19:09 dnolen: (could be wrong about that, but I don't think so)

19:09 ravster: I'll just change that to a cond or something

19:10 thanks amalloy, dnolen

19:16 _Vi: Why can't I neither log in to dev.clojure.org as "_Vi", nor recover the password/username, nor re-register as "_Vi" ("A user with this username already exists")

19:19 ravster: d'oh, or I could just use map? and seq?

19:19 * ravster smart

19:19 * ravster lisp programmer

19:19 ravster: derp derp

19:22 yedi: does anyone know how to run scripts on an rds instance?

19:28 bbloom: _Vi: so both fipp and core pprint use multimethods for interpreting data structures (instead of protocols) which (according to some simple profiling) is a major cause of slowdown

19:30 _Vi: Does it mean "slow by design" or "we'll reimplement with protocols"?

19:32 bbloom: well from i can tell, about 2/3rds of the cost isn't printing, it's translating the EDN structures into a printable structure, which can likely be done with protocols w/o much loss of flexibility

19:35 _Vi: Can it be blazing-fast after this?

19:35 bbloom: _Vi: it's never gonna be as fast as prn

19:36 _Vi: Means at least to measure "N per cents against prn", not "N times"...

19:39 pl6306: How do I used reduce to add a new line character to a seq of strings?

19:40 _Vi: pl6306, Do you mean something like (map #(str % "\n") seq-of-strings) ?

19:41 pl6306: I wanted the end result to be a string. So I thought (reduce #(str % "\n") str-seq) would work but it doesn't

19:42 bbloom: _Vi: holy hell. multimethods are SLOW

19:42 i knew they were slow, but wow, crazy slow

19:42 nightfly__: pl6306: try the three argument variable of reduce

19:42 andyfingerhut: pl6306: Wrap that in (apply str ...) and you should get the result you want

19:42 nightfly__: *variant

19:43 andyfingerhut: pl6306: Ignore that. I must have been on drugs to say it.

19:43 bbloom: _Vi: your test takes about 2,000ms on my machine, but with protocols instead of multimethods, it needs about 600ms

19:43 andyfingerhut: I was thinking of map, not reduce.

19:44 pl6306: ok

19:45 I think it should be a simple solution.

19:46 IamDrowsy: what about (reduce #(str %1 "\n" %2) str-seq)

19:47 bbloom: _Vi: still, same test only needs 12ms with prn, heh

19:48 _Vi: bbloom, Can there be some compromise solution with 30 ms?

19:48 pl6306: (reduce #(str %1 "\n" %2) str-seq)  works but why 2 args and not one?

19:48 IamDrowsy: because reduce always needs a 2 arg fn

19:49 pl6306: Got it thanks!

19:50 bbloom: _Vi: dunno yet, i've been profiling/optimzing for all of 10 minutes :-P

20:00 _Vi: I'll try a few more optimizations & then i'll post a follow up on stackoverflow later tonight

20:00 got some other stuff to take care of first

20:14 callen: I've generally deployed Clojure apps behind Nginx, what do you guys do?

20:26 nightfly__: Usually do the same for all web stuff

20:35 gfredericks: I've been fine with jetty so far; that's usually just json servers though

20:36 callen: gfredericks: on port 80?

20:36 gfredericks: the idea behind using nginx is for static content so that JVM load isn't wasted on serving css/js/img

20:37 gfredericks: right; I didn't need either static content or particular ports

20:44 callen: gfredericks: ah yes, well that's bloody convenient.

20:44 gfredericks: :)

20:44 callen: I'll stick with what I did last time then.

20:44 nginx + jetty

20:44 gfredericks: that's why I qualified with "just json servers"

20:44 callen: and hope to fuck I don't need websockets/async

20:44 gfredericks: I knows, I knows. your use-case is about as a common as anything these days. Not a lot of libraries for us HTML schleppers.

20:46 bbloom: any suggestions on how to minimize the perf cost of ArraySeq? It seems that it calls java.lang.Class.getComponentType, which is surprisingly slow

21:26 tieTYT: i'm using seesaw. Can anyone tell me why my "destination-shortcuts" is only rendering on the right half of the vertical-panel it's inside of? https://www.refheap.com/paste/177a7f1ecb15b7db085fa858c

21:32 amalloy: bbloom: let me know if you find anything. it's been bothering me too, recently

21:33 bbloom: amalloy: the ArraySeq thing?

21:33 yeah, i think i did find something....

21:33 sanity check me real quick?

21:33 amalloy: sure

21:33 bbloom: in ArraySeq, look at the ct field, which is initialized via array.getClass().getComponentType()

21:34 notice it is only ever used to call Reflector.prepRet

21:34 then go look at prepRet

21:34 tieTYT: i wrapped it in a horizontal-panel and that fixed my issue

21:35 bbloom: amalloy: my thought is that if the array component type is object (as it is for RestFn calls) then that prepRet function is a no-op

21:35 amalloy: in which case, i think it can be eliminated from ArraySeq

21:35 amalloy: let me know if that makes sense

21:39 if i am right about this, there's a pretty decent perf boost to be had for all usages of rest functions.... but i'm not sure yet

21:40 amalloy: bbloom: sounds right, but i don't have time to double-check the details for you right now

21:42 bbloom: amalloy: actually, there are all these specialized versions below: ArraySeq_int, etc

21:45 amalloy: ok, i'll run a test or two & then mail the dev list

22:22 jasonjckn: dnolen: hey david, does core.logic support ("exists in set" set el) ?

22:22 dnolen: i looked around didn't see anything

22:22 dnolen: I could use a list but then you get dupes and every permutation

22:23 bbloom: if i make a perf patch for clojure, what should i file the ticket as?

22:26 amalloy: bbloom: enhancement for sure

22:44 dnolen: jasonjckn: no there's no set membership ... yet, we're working on CLP(Set) next

22:46 jasonjckn: dnolen: cool, who's we?

22:47 dnolen: jasonjckn: Nada Amin is also interested in working on it

22:48 jasonjckn: she's already done a version in plain Scheme miniKanren, and Claire Alvis has done a version on top of cKanren, so it shouldn't be difficult to translate what they've done.

22:48 bbloom: amalloy: http://dev.clojure.org/jira/browse/CLJ-1200

22:49 dnolen: jasonjckn: re: min/max, I just need to power through some refactoring and I think I can at least get basic min/max support out the door.

22:49 bbloom: dnolen: since i had never seen RestFn prior to our discussion a week or so ago, you might be interested. but probably not

22:50 jasonjckn: dnolen: awesome! yah I think both set and min/max are blockers for a storm CLP scheduler

22:50 dnolen: bbloom: nice

22:50 amalloy: bbloom: i'm curious what library you found it in

22:51 dnolen: jasonjckn: min/max is fairly simple. I'm not sure what you need as far as set membership, like just for integers?

22:51 bbloom: amalloy: fipp

22:51 amalloy: i noticed it in cheshire, myself, but couldn't untangle what was going on in reflector and arrayseq; thanks again for finding that

22:53 bbloom: amalloy: yeah, i'm not sure what that prepRet thing is really needed for. i think there are a bunch of calls to it that can be eliminated

22:54 amalloy: bbloom: it looks to me like all prepRet does is convert (Boolean. "false") to Boolean/FALSE

22:55 bbloom: amalloy: which is a leaky thing anyway that i'm not sure is worth doing...

22:55 amalloy: it used to do more stuff.... git blame is kinda messy for it

22:55 dnolen: jasonjckn: I've been looking fairly closely at the feature listed here - http://www.swi-prolog.org/man/clpfd.html, if you have any feedback about that would be useful.

22:55 s/feature/features

22:56 amalloy: bbloom: right, it looks like it's trying to convert boxed objects to some canonical representation iff the expected return type is a primitive

22:56 but the only one that's not commented out is for booleans

22:57 bbloom: amalloy: which i think only made sense prior to the introduction of the various specialized ArraySeq impls

22:57 callen: "Could not connect to JRun Server." Ohhh acm. You're so adorable.

22:57 amalloy: maybe

Logging service provided by n01se.net