#clojure log - May 05 2014

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

1:03 rhg135: Any preferred way to do io in a swap! once?

1:08 I was thinking a deftype to hold state and an io fn comparing only the state but that feels hackish

1:40 Viesti: hmm, looking for memory sensitive caching (soft/weak reference)

1:42 saw that core.memoize had one (Release 0.5.1 on 2011.12.13 Removed SoftCache memoization) and the current (0.5.6) release note mentions softcache again in Plans section (SoftCache backed memoization)

1:44 rhg135: It's extensible, I'd write one

1:58 Viesti: rhg135: that did occur to me also, was wondering if one is in the works, so that I don't code in the bugs :)

1:59 rhg135: Ic, I forget who wrote it

2:14 ticking: is there a way to check if a channel is still open except for reading it? I need this information for a debug log.

2:15 s/channel/core.async/chan

2:16 guns: ticking: clojure.core.async.impl.protocols/closed?

2:16 Although I'm not sure if that's just an implementation detail

2:17 ticking: guns: a thanks, that's why it doesn't show up in the api ^^

2:17 guns: I'll use it with care ^^

3:11 waynr: is it possible to copy a directory from a project's resources or does it have to be done file-by-file

3:13 crispin: hi there peeps!

3:13 Im pulling my hair out with gen-class!

3:14 guns: waynr: only file-by-file if you care about resources from jars

3:14 TEttinger: crispin, that's something I'm familiar with, kinda

3:14 crispin: I know its something to do with AOT... but I just cant get it working

3:14 I keep getting ClassNotFoundException

3:14 any definitive document on this?

3:15 how do I _find_ my class?

3:15 (I wish proxy could create new methods, not just subclass :P )

3:16 TEttinger: crispin, uh some code would help. the file with the ns you are trying to gen-class and the project.clj , on gist would be easiest?

3:17 crispin: ok. I'm using (gen-class... not :gen-class

3:17 waynr: guns: would it be possible to get a list of files in <dir> within the jar using clojure.java.io or something like it?

3:17 crispin: will gist it up

3:17 TEttinger: thanks

3:17 sm0ke: ,(let [{:keys [x y]} {:rs/x 1 :rx/y 2}] (prn x y))

3:17 clojurebot: nil nil\n

3:17 guns: waynr: of course

3:17 sm0ke: ,(let [{:keys [x y]} {:rs/x 1 :rs/y 2}] (prn x y))

3:17 clojurebot: nil nil\n

3:18 sm0ke: how do i destrucutre those keywords?

3:18 ,(let [{:keys [rs/x rs/y]} {:rs/x 1 :rs/y 2}] (prn x y))

3:18 clojurebot: 1 2\n

3:18 sm0ke: whoa!

3:19 this must be a joke! doesnt work on my repl

3:20 TEttinger: I'm surprised you can have symbols with / in them

3:20 ,://

3:20 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: ://>

3:20 TEttinger: ,:oh//

3:20 clojurebot: :oh//

3:20 guns: Using said symbols is another matter

3:21 sm0ke: that gives valid error on my repl, Can't let qualified name: rs/y

3:21 how the hell it worked here

3:21 ,(let [{:keys [rs/x rs/y]} {:rs/x 1 :rs/y 2}] (prn x y))

3:21 clojurebot: 1 2\n

3:21 TEttinger: probably because there's sandboxes and such

3:21 guns: sm0ke: the behavior changed in 1.6.0

3:21 TEttinger: or that!

3:21 sm0ke: anyway to handle this pre 1.6?

3:22 crispin: https://www.refheap.com/85128

3:22 TEttinger: ,(print *clojure-version*)

3:22 clojurebot: {:major 1, :minor 6, :incremental 0, :qualifier nil}

3:22 guns: sm0ke: ,(let [{x :rs/x} {:rs/x 1}] x)

3:22 crispin: TEttinger: not sure if this is even the right approach. But I can't seem to get the class foiund no matter how I arrange it

3:22 amalloy: TEttinger: oh// reads as "the symbol named / in the namespace oh"

3:22 TEttinger: taking a look, crispin

3:23 sm0ke: ugh, keep on forgetting the basic

3:23 thanks guns

3:24 (inc guns)

3:24 lazybot: ⇒ 2

3:24 TEttinger: crispin, does "lein compile" throw any errors, from the command line

3:24 crispin: TEttinger: no

3:25 the app runs fine too

3:25 TEttinger: I'm guessing it has to do with the ns not matching the class name

3:26 waynr: is there a simple way to preserver directory structure when copying directories from the classpath?

3:26 crispin: which ns? com.signiq.jwsapp.download?

3:26 guns: waynr: I should have mentioned that you don't generally want to search the classpath for resources

3:26 TEttinger: check the compiled .class files, crispin? if there isn't a com/signiq/jwsapp/download folder, then we know something's up

3:26 guns: the usual approach is to keep a static list

3:27 crispin: yes!

3:27 theres no download.class

3:28 TEttinger: there's no folder called download, with a class called Connection in it?

3:28 crispin: no folder.

3:28 just all core classes

3:29 TEttinger: oh that's interesting

3:29 it doesn't have any of your ns segments as folders?

3:30 crispin: it has classes/com/signiq/jwsapp/

3:30 then in that, core.class, core__init.class, core....

3:30 TEttinger: right

3:30 crispin: lots of core classes

3:30 TEttinger: that's the result of AOT compiling your core.clj

3:31 crispin: right

3:31 can I tell AOT to compile the download.clj into a class?

3:31 TEttinger: I would like to see that project.clj if you can paste it

3:31 it might be a simple fix

3:31 crispin: https://www.refheap.com/85129

3:34 TEttinger: you need in there, before or after ":main com.signiq.jwsapp.core", :aot [com.signiq.jwsapp.download] I think

3:34 crispin: aaahhh. let me try

3:35 I figured it may have been aot related

3:35 aa-ha. lein compile now reports: Compiling com.signiq.jwsapp.download

3:35 TEttinger: awesome! you're a legend

3:36 it finds the class now! Theres another error, lol

3:36 TEttinger: hooray!

3:36 crispin: but it finds the class!

3:36 sweet!

3:36 waynr: guns: okay, well i have template files that i want to be deployed by the project to the current directory

3:36 crispin: thanks a bunch

3:36 TEttinger: you can add more classes to that :aot vector if you need more gen-class classes

3:36 crispin: ok.

3:36 and it will compile all the gen-classes in a file?

3:36 so if I have a few with different prefixes?

3:36 TEttinger: in their own files I think

3:37 crispin: ok. man I love clojure, but java sucks :P

3:37 its always the dealing with java bits that hurts

3:37 TEttinger: a single Java class has one .class file, the clojure equivalent is a .class file for the ns that calls a bunch of similarly-named .class files

3:37 crispin: right

3:37 guns: waynr: Your templates are packaged in your jar, so you know them beforehand right? Or you can spit the list of templates to a file in a build hook, then read from that at runtime

3:39 waynr: the templates are in "./resources/templates" and all i want to do is copy that directory from the jar to local directory

3:42 guns: waynr: You're free to scan the classpath for all files matching the prefix templates/, but it might be slow, and it might include files from other jars

3:43 waynr: maybe i'll give it a project-specific prefix

3:43 crispin: ok, FYI. multiple (gen-class... classes get compiled into multiple.class files in the class directory. So if I have two gen-classes in a .clj file I get two output .class files

3:43 TEttinger: yes

4:25 martinklepsch: (with-open [z (java.util.zip.ZipFile. fileName) e (find-xml z) r (.getInputStream z e)]

4:25 wade: any one have a best solution for the 2048 game in Clojure?

4:26 martinklepsch: I have something like this and thought that way I could get the contents of the xml file but the .getInputStream method returns a ZipEntry? (which is not closeable

4:27 TEttinger: wade: I thought there was a random element to 2048?

4:30 clgv: wade: what game? (link?)

4:32 martinklepsch: the result of `find-xml` is probably not closeable either. so just use a `let? inside the `with-open`

4:33 TEttinger: clgv: http://gabrielecirulli.github.io/2048/

4:33 it's an excellent idle time waster

4:34 martinklepsch: clgv, turns out that error was because I renamed the function but executed the same snippet I had in light table again and again

4:34 TEttinger: also once you've played that, there's the marginally harder http://doge2048.com/

4:35 Morgawr: mm.. I was playing around memoizing some functions in my (single-threaded) code, it's very CPU-intensive code and adding memoization doesn't help (I always have different values) but I don't understand why when I add memoization to my function the CPU usage goes to 100% on all cores

4:35 does memoize use multithreading? I can't seem to find any multithreading done in the implementation but all my cores go to 100% CPU

4:36 using visualvm it seems that most of the time is spent in clojure.lang.Util.dohasheq() and clojure.lang.PersistentHashMap$ArrayNode.find()

4:36 ArrayNode.find() doesn't seem to be doing any multithreading and I doubt dohasheq() does that either

4:37 clgv: Morgawr: probably the Garbage Collector using all available cores

4:37 Morgawr: clgv: ah, good point

4:37 that makes sense

4:37 clgv: Morgawr: does VisualVM have a view for GC? Yourkit has

4:38 Morgawr: yeah

4:39 yeah it seems to be the GC

4:39 the used heap goes up and then suddenly all my cores go to 100% and it goes down again

4:39 clgv: TEttinger: ah. right. maybe tractable via machine learning to find ratings for good moves

4:40 Morgawr: maybe you have to rethink the granularity of your memoization

4:40 Morgawr: clgv: yeah yeah, I already know it wasn't a good idea to memoize that function, it was just a test

4:40 clgv: Morgawr: what types are the arguments of the function you memoize?

4:40 Morgawr: they are records

4:40 that hold doubles

4:40 so it makes no sense to use memoization in the first place

4:40 because the double values are going to be different most of the time

4:41 it was just a test

4:41 martinklepsch: having an InputStream, whats the easiest way to make that a string?

4:42 penthief: (.readLine (java.io.BufferedReader. (java.io.InputStreamReader. is)))

4:43 guns: Can't you slurp an InputStream?

4:43 clgv: Morgawr: yeah. if you know upfront that all invocations will very likely have different values dont bother trying memoization ;)

4:44 Morgawr: clgv: yup :P

4:44 llasram: guns, martinklepsch, penthief: yes, `slurp`

4:44 penthief: Thanks!

4:44 guns: clojure.java.io/Coercions is very convenient

4:45 llasram: Indeedy. Extra so since as a protocol it is open to extension to additional types

4:45 martinklepsch: llasram, guns, penthief, that indeed seems to work

4:46 guns, haha that was highlighted as a link. kinda funny where it gets you

4:46 wade: whois TEttinger

4:48 hennry: Hello i want to reload the repl from the code there is any way Actually i want to refresh the page

4:49 TEttinger: who is TEttinger, really... what is TEttinger...

4:49 clgv: $karma TEttinger

4:49 lazybot: TEttinger has karma 17.

4:49 sm0ke: hennry: you need to explain it better

4:49 clgv: someone with karma 17 it seems ;)

4:49 TEttinger: $karma clgv

4:49 lazybot: clgv has karma 16.

4:49 TEttinger: (inc clgv)

4:49 lazybot: ⇒ 17

4:49 clgv: lol :P

4:50 Morgawr: $karma Morgawr

4:50 lazybot: Morgawr has karma 1.

4:50 Morgawr: :D

4:50 sm0ke: (dec clgv)

4:50 TEttinger: (inc Morgawr)

4:50 lazybot: ⇒ 2

4:50 ⇒ 16

4:50 clgv: now we are indistinguishable with respect to that "metric" ;)

4:50 Morgawr: woo

4:50 sm0ke: whoa!

4:50 clgv: or not...

4:50 sm0ke: sorry about that

4:50 (inc clgv)

4:50 lazybot: ⇒ 17

4:50 TEttinger: good ol' karma

4:50 $karma technomancy

4:50 lazybot: technomancy has karma 107.

4:50 Morgawr: turning good people into terrible popularity slaves

4:51 $karma rhickey

4:51 lazybot: rhickey has karma 2.

4:51 Morgawr: we are one!

4:51 $karma Morgawr

4:51 lazybot: Morgawr has karma 2.

4:51 TEttinger: haha

4:52 clgv: it should decrease karma to add it to often to others ;)

4:52 hennry: <sm0ke> i want to refresh the page there are many ways in ajax and jquery but i want to do this from clojure there is any process, i think this is happened by reload the repl in clojure

4:52 TEttinger: clojure or clojurescript, to refresh a page, hennry?

4:53 hennry: clojure

4:53 <TEttinger> by clojure

4:54 sm0ke: sorry i am unable to comprehend

5:00 penthief: hennry: "by clojure" implies this code is executing on the server. There is no sensible way for a server to refresh a client whether using clojure or not.

5:21 clgv: henry: you need to describe you problem technically more exact. it often helps to post a minimal example of your problem code on refheap.com

5:35 martinklepsch: is there a way to handle an open input stream to another function or reopen it?

5:36 llasram: martinklepsch: What are you trying to accomplish at a slightly higher level?

5:37 martinklepsch: llasram, pass a large input stream from an xml file to a function that splits it into a chunks. that split function previously took a file as argument but I refactored things and now I'd like to pass the input stream directly

5:37 (the input stream comes from a zip file so referencing the file directly didn't work anymore

5:38 llasram: What's preventing you from passing the input stream like any other argument?

5:38 martinklepsch: llasram, here's some code: https://www.refheap.com/85131

5:38 llasram: Oh, is the function closing the entry stream -> closes the overall file?

5:39 martinklepsch: yeah, it uses with-open and this closes the input stream

5:39 I think that's the problem — maybe putting both things into one with-open clause would fix it but thats more of a compromise than a solution

5:40 llasram: Yeah, this is a general problem with Java I/O interfaces. Apache Commons IO has a CloseShieldInputStream which lets you prevent callees from closing the stream you pass in

5:46 martinklepsch: llasram, this seems to be an acceptable workaround

5:46 https://www.refheap.com/85132

5:47 llasram: martinklepsch: Well, except that closing a Reader will close the underlying InputStream too

5:48 martinklepsch: yeah, but in that case I'm done anyways. the splitting is hopefully all IO work necessary

5:49 visof: how can i set the paths of dependencies at project.clj if it's at local file system?

5:49 llasram: Oh, I see. I'm obviously not awake yet :-) I was thinking about an issue on the output side of the Java stdlib ZIP interfaces

5:51 visof: (a) You don't. See https://github.com/technomancy/leiningen/wiki/Repeatability

5:52 visof: (b) There are ways to refer to local JAR files, but they are hacks, so first make sure something is actually preventing you from doing it right

5:52 visof: llasram: i'm using buggy lib which i need to patch it then test again, what do you suggest to do this?

5:53 llasram: visof: Is the buggy lib also a Clojure project using Leiningen?

5:53 visof: llasram: yep

5:53 llasram: visof: Checkout dependencies: https://github.com/technomancy/leiningen/wiki/Repeatability

5:53 ooops, wrong link

5:54 https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

5:54 There we go

5:57 visof: llasram: so i should put the patched jars at checkouts dir at my root project?

5:57 llasram: Um, no

5:58 You symlink to the root of your checkout of the source for the other project

5:58 visof: llasram: symlink to the directory of the other projects not jar?

5:59 llasram: Yes. No JARs. Generally if you are directly handling JAR files, then you're fighting against the grain

6:02 visof: llasram: okay thanks

6:35 clgv: visof: you could also "lein install" the buggy lib provided it is a lein project

6:47 visof: clgv: can you help me to make jirpah working please?

6:47 clgv: visof: I don't even know what that is ;)

6:48 visof: clgv: https://github.com/ninjudd/jiraph

6:48 clgv: just want to make the sample in this page work

6:48 clgv: can you try at your owns?

6:51 clgv: visof: well just check it out. maybe rename the version (e.g. in project.clj too avoid accidental problems later and then "lein install". after that you can add it as normal dependency to your other project on that same development machine

6:51 but checkout dependency would work as well

6:52 visof: clgv: can you do the just the basic stuff for it at your own?

6:52 clgv: visof: no. no time for that

6:52 visof: okay

6:54 clgv: https://www.refheap.com/85110

6:54 clgv: that's the error i got

6:55 clgv: visof: well an error without a description what you were trying to do does not help much

6:55 TEttinger: ,(doc applied)

6:55 clojurebot: Excuse me?

6:55 TEttinger: (doc applied)

6:55 clojurebot: excusez-moi

6:56 TEttinger: well that could be part of it?

6:56 clgv: ~applied

6:56 clojurebot: Cool story bro.

6:56 TEttinger: ##(doc applied)

6:56 lazybot: java.lang.RuntimeException: Unable to resolve var: applied in this context

6:56 TEttinger: ah

6:56 clgv: TEttinger: what are you looking for?

6:56 TEttinger: it definitely is something it thinks should exist but doesn't, which is probably not in clojure.core...

6:56 that refheap, second error

6:57 Exception in thread "main" java.lang.IllegalAccessError: applied does not exist

6:57 clgv: ah. never heard that symbol before

6:58 ,(apropos "applied")

6:58 clojurebot: ()

6:58 clgv: $apropos "applied"

6:58 ok that does not exist..

6:58 visof: clgv: https://www.refheap.com/85134 core.clj

6:59 clgv: https://www.refheap.com/85135 project.clj

6:59 clgv: https://www.refheap.com/85110 error

7:01 clgv: visof: assuming these versions mean anything why don't you just try 0.12.2

7:01 ?

7:02 visof: 0.12.2-alpha1

7:02 ?

7:02 clgv: no. the idea is to use something without "alpha" or "beta" in the version to check whether that works ;)

7:04 visof: clgv: works but the same error i got

7:05 clgv: visof: does "lein check" in the jiraph project work without errors?

7:06 visof: clgv: That's not a task. Use "lein help" to list all tasks.

7:06 clgv: visof: upgrade ;) $ lein help check => "Check syntax and warn on reflection."

7:07 visof: upgrade lein?

7:07 clgv: yes

7:07 visof: okay

7:08 f3ew: How do I do the equivalent of if (/^pattern/) { (undef, $foo, bar) =~ /(pattern)\.(data)\.(other.data)/ } ?

7:08 The regex documentation isn't particularly helpful for this

7:09 clgv: f3ew: clojure.string/replace?

7:10 f3ew: I'm just trying to capture matched patterns

7:10 * f3ew RTFMs more

7:11 f3ew: No, I only want to match the pattern, capture some data if the string matches and then do other processing on the data

7:11 clgv: re-find? re-matches?

7:12 f3ew: re-matches is what I've been looking at

7:13 TEttinger: f3ew, was that snippet perl?

7:13 f3ew: Hmmm, I wonder if I should just assign (re-matches #"^pattern) to a variable, and then apply variable <actual string>

7:13 TEttinger: yes

7:13 TEttinger: I have no idea quite what it does...

7:14 I usually use http://www.regular-expressions.info/brackets.html for when I have regex questions

7:14 f3ew: if (match pattern) { capture three values , assign them to three variables }

7:14 This isn't a regex question :)

7:15 TEttinger: likely re-matches or re-seq ?

7:15 (doc re-seq)

7:15 clojurebot: "([re s]); Returns a lazy sequence of successive matches of pattern in string, using java.util.regex.Matcher.find(), each such match processed with re-groups."

7:15 f3ew: Yeah, my question was about applying those

7:17 TEttinger: so you're trying to get out of a string, "a.b.c" a, say, vector, of 3 elements, here "a", "b", and "c"

7:17 clgv: ,(let [s "12 3 456"](when-let [[_ a b c] (seq (re-find #"(\d+) (\d+) (\d+)" s))] [a b c]))

7:17 clojurebot: ["12" "3" "456"]

7:17 clgv: f3ew: something like that? ^^

7:17 f3ew: that looks useful, thanks

7:17 TEttinger: that looks about right to me

7:17 f3ew: Except I don't know s yet

7:18 TEttinger: sure, you can use an arg in its place

7:18 clgv: f3ew: yeah that is included for the example as constant ;)

7:19 TEttinger: ,((fn [s](when-let [[_ a b c] (seq (re-find #"(\d+)\.(\d+)\.(\d+)" s))] [a b c])) "alpha.beta.com") ; you'd use what's in the fn as a defn more likely

7:19 clojurebot: nil

7:19 TEttinger: oh right

7:19 ,((fn [s](when-let [[_ a b c] (seq (re-find #"(\w+)\.(\w+)\.(\w+)" s))] [a b c])) "alpha.beta.com") ; you'd use what's in the fn as a defn more likely

7:19 clojurebot: ["alpha" "beta" "com"]

7:21 clgv: f3ew: TEttinger: if you write a function you won't destructure the result just to reassemble it to a vector again ;)

7:22 TEttinger: haha fair point, I didn't read it very carefully

7:22 agarman: ,((fn [s] (when-let [[a b c] (re-seq #"\w+" s)] [a b c])) "alpha.beta.com")

7:22 clojurebot: ["alpha" "beta" "com"]

7:22 TEttinger: although I can't quite think of a better way

7:23 agarman I think can!

7:23 that's nice

7:23 (inc agarman)

7:23 lazybot: ⇒ 1

7:23 TEttinger: (inc clgv)

7:23 lazybot: ⇒ 18

7:24 visof: clgv: https://www.refheap.com/85137 result of lein check

7:27 clgv: visof: great. you are sure that you want to use that library?

7:28 visof: clgv: what do you mean

7:28 i have added flatland/useful to project.clj

7:42 clgv: visof: I mean that it is probably not a good idea to start using a library that causes so much trouble just from referencing it in you own project

7:43 visof: if there is really no alternative I'd get in touch with its developers/maintainers to get the problems fixed

7:43 visof: clgv: i'm forced to use it to check the performance with other libs

7:43 clgv: someone here told it's not a user-friendly

7:44 clgv: visof: well, amalloy might be around here later today. maybe you can catch him

7:44 visof: clgv: one of its dev

7:44 clgv: amalloy who told this

7:44 amalloy told it's not user friendly and suggest to not use it

7:44 clgv: visof: from what I saw of you error messages it is not usable at all...

7:45 visof: clgv: what do you mean?

7:46 clgv: visof: requiring a namespace of a library should not result in any exceptions. I'd say that's a minimum requirement for a "usable" library ;)

7:46 visof: clgv: all i want if you can help just copy/paste the project.clj and core.clj and try at your own and you are going to get some more sight on this

7:47 clgv: visof: I have seen enough. I wouldnt touch a library like that for the above reason

7:49 agarman: it's jiraph, not useful that's failing?

7:50 clgv: agarman: yes, jiraph

10:04 coventry: visof: Might be a dependency conflict, which "lein deps :tree" might help you to determine.

10:07 sritchie: any lein-voom users here?

10:07 bmabey: are you using lein-voom?

10:07 TEttinger: what's lein-voom?

10:07 clgv: sounds explosive :O

10:08 TEttinger: that's neat sritchie. does it work?

10:08 sritchie: the voom plugin?

10:08 well, that's what I'm working on, figuring out the right workflow for it

10:09 TEttinger: clgv, it's named after something explosive https://github.com/LonoCloud/lein-voom

10:09 clgv: TEttinger: :P

10:10 the readme doesnt tell anything about configuration...

10:11 sritchie: do you use leiningen checkouts?

10:11 sritchie: not really - I did when I was developing on Cascalog more

10:11 for the shared util libraries, etc

10:12 bmabey: sritchie: no, not yet, but it is on my TODO list

10:12 sritchie: saw your pull req, thought you might have some insight

10:12 I'm just watching Aaron's clojure/west talk now, we'll see how it goes

10:13 bmabey: sritchie: I've had some conversations with Aaron about it and saw his talk at ClojureWest

10:13 sritchie: what isn't documented, and I don't fully understand yet, is the box part

10:13 sritchie: I haven't seen the box thing

10:13 bmabey: I'm going to start writing some batch jobs that need to share my database and utility code, and figured I'd try to do things right from the start

10:14 and not get into the whole dependency mess that haunted me with the Twitter open source projects

10:14 voom seems like a nice approach

10:14 bmabey: sritchie: also, the CI daemon for continuous freshening isn't done yet (last I heard).. so it is just up to the devs to run freshen (or batch scripts)

10:14 clgv: with only the readme I have no idea how to use lein-voom...

10:14 sritchie: clgv: :)

10:14 bmabey: yeah, the approach is solid and they have put a lot of time and effort into it so I think it is worth adopting

10:14 it is either that or use maven, etc

10:15 clgv: you can add that quote to an issue about the docs if you should create one ;)

10:15 sritchie: clgv: sounds like you should create one

10:15 bmabey: well, maven's still involved, I guess - I'm going the s3-private-wagon road for now

10:16 clgv: sritchie: well the point is I don't even see what it provides ...

10:16 bmabey: sritchie: true, but the whole snapshotting thing can be solved if you go into pure pom land

10:16 from what I understand at least... I'd like to stay with lein so I'm glad len-voom exists :)

10:17 sritchie: ah, I see what you mean

10:17 bmabey: clgv: if you work on a large project comprsied of several independent projects each moving quickly lein-voom automates the process of making commit-level releases so that the projects are always using the latest deps but don't have to rely on dangerouse SNAPSHOTs

10:17 sritchie: bmabey: yeah dude, do NOT go that route

10:17 what a nightmare

10:18 bmabey: sritchie: B

10:18 sritchie: BTW, I used your om-timer the other day to explore om and react, pretty cool stuff. thanks for sharing :)

10:18 sritchie: bmabey: the question I had, the reason I pinged, was that I've been seeing examples in the github issues on that project that include metadata on the various voom dependencies

10:18 nice!

10:18 clgv: hm ok found a project.clj on github using it.

10:18 sritchie: clgv: link?

10:19 tbaldridge: Is staying at the latest release on everything really that important? What projects move that quickly?

10:19 clgv: seems like you just define the git repo via metadata on the dep right?

10:19 sritchie: https://github.com/vlacs/galleon/blob/d329e2498a13840aa638305cc2d7a1feb07fa7fa/project.clj

10:20 sritchie: tbaldridge: it's really annoying when you modify a util library to go doa whole release, bump the deps, submit a bunch of pull reqs...

10:20 tbaldridge: so what happens is you just stick the code in whatever project you're currently working on

10:20 tbaldridge: and then later, do some big refactor of all your projects to get the code back where it belongs

10:20 tbaldridge: or use lein checkouts?

10:20 sritchie: yeah, that's great if it's just you

10:20 but then someone else on your team gets on to code, and nothing builds because you forgot to push the util lib,

10:21 or they need to go restart their lein processes,

10:21 and then the pressure of how annoying this is just forces you into a single repo

10:21 and you do what twitter did, and actually create an ENORMOUS MONO REPO

10:22 but you still want to open source stuff, because you like open source, so you write tools that carve out specific namespaces, bundle them up and release those as specific artifacts… but then you accidentally include the same namespace in multiple artifacts, and someone includes both, but with different versions,

10:23 and they spend hellish hours trying to debug problems that result from two versions of a clj file on the classpath, one with the bugfix, one without, so SOMETIMES the depending project manifests the bug, sometimes not,

10:23 tbaldridge: and then, oh my god, you write a bunch of build tooling to detect diamond dependencies within your mono repo… and on and on

10:23 bmabey: yeah, util libs that are shared among several of our projects are the main use case. We want them to be up to date as soon as possible to catch integration problems ASAP

10:23 sritchie: yup

10:24 I have a nice async stripe lib that uses schema that I want to be able to release

10:24 and quickly integrate changes

10:24 bmabey: once a project is released using voom, do you just peg it to some arbitrary version and use voom for all release?

10:24 releases?

10:25 bmabey: what's not clear is how to interleave true releases into the voom flow, for open source work

10:26 bmabey: sritchie: I think for true releases you would just bump the version deps manually in the project.clj, make a releases, and then switch back to voom.. just like you would with a regular release->SNAPSHOT cycle

10:26 Glenjamin: bmabey: can't you just depend on a semver range of your util lib, then cut a series of stable releases?

10:26 tbaldridge: Is this really that this big of a problem though? Every large codebase I've worked on either used larger modules (so less coupling between modules), or more regulated releases.

10:26 Glenjamin: tbaldridge: if the tools supported it, do you think you'd go for smaller modules?

10:27 sritchie: tbaldridge how did you regulate releases?

10:27 Glenjamin: I don't think that leiningen has good support for semver ranges

10:27 and if you don't have good tooling for actually detecting semver bumps,

10:27 which is REALLY hard in a non-typed lang,

10:28 bmabey: Glenjamin: yes, I think that approach works well and that is what we've been doing but having SNAPSHOT still seems scary

10:28 tbaldridge: One project I worked on had a "owner" for each project. You would submit a PR, and in about a day it would be released as a new lib version.

10:29 sritchie: tbaldridge: that sounds really nice :)

10:29 Glenjamin: tbaldridge: in theory, if your modules are small enough most of them don't change much

10:29 or the number of breaking changes is very small

10:29 sritchie: tbaldridge: but then a module has to be big enough that a person can make a fulltime job out of it

10:30 tbaldridge: I think some of the problems you're hitting is that they are too small. Having problems with diamond deps is a big code smell IMO.

10:30 sritchie: bmabey: for adding a voom proj for the first time, I guess you just go look up the voom version and add it manually

10:30 Glenjamin: the main one for me is "utility" libraries

10:30 tbaldridge: actually scratch that, I was thinking "circular deps" when I heard diamond deps.

10:31 sritchie: yeah, diamond deps just happen

10:31 tbaldridge: the clojure lib being a huge example :)

10:31 foofoobar: Hi. Is there some online clojure tutorial/book you can recommend? Like learn you a haskell, just for clojure :)

10:31 Glenjamin: we can't just keep putting all the useful stuff in core, and we can't require every project to bump their dependencies when a new version of a lib comes out

10:31 bmabey: foofoobar: I haven't read it but this looks similar in spirit: http://www.braveclojure.com/

10:32 sritchie: bmabey: do you know what's going on with the metadata on different project deps?

10:32 Glenjamin: i'm a fan of the approach taken by http://aphyr.com/tags/Clojure-from-the-ground-up

10:32 sritchie: bmabey: just checking, then I'll watch the video :) and write something up when I figure it out

10:32 Glenjamin: i think the rules for dependencies should be different if you're building an app vs a lib - at the mo lein doesn't distinguish afaik

10:32 bmabey: sritchie: sorry, it has been a while since I investigated it so I don't recall the details. I remember that I was able to get it to work without much hassle

10:33 foofoobar: thanks!

10:33 bmabey: sritchie: bug @0x1B on twitter if you can't figure it out

10:33 sritchie: nice, thanks

10:35 bmabey: sritchie: BTW, OT, but did you get into the Wasatch 100?

10:36 sritchie: bmabey: nope! nor the hardrock

10:36 now I have to do another one of these damned 100s to apply again

10:36 keep me on the list for running adventures :)

10:36 bmabey: sritchie: uhh.. sorry! sure thing

10:36 sritchie: let me know if you make it out to Boulder, or if you want to come visit

10:37 there's a bunch of fun stuff to do off in rocky mountain

10:37 back soon, dog part time

10:37 park*

10:37 colorado life ftw

10:38 bmabey: cool, I'll have to check out the list of boulder races

10:39 tbaldridge: srcerer: you're in Boulder?

10:39 sritchie: you're in Boulder?

10:40 foofoobar: So I'm following http://www.braveclojure.com/getting-started/ and just created an project with "lein new projectname"

10:41 I'm inside this folder now and run "lein run", but the only thing I get is No :main namespace specified in project.clj.

10:44 technomancy: foofoobar: do lein new app projectname if you want to have an entry point defined

10:46 foofoobar: technomancy, I just read in the comments that I need to updae my lein to 2.X

10:48 hyPiRion: foofoobar: yeah, that's a good idea too

11:05 clgv: foofoobar: otherwise just use "lein repl" and play with the REPL ;)

11:13 Morgawr: I have a record defined in a namespace and I try to use its constructor from another namespace and it doesn't work, it says class not found

11:13 if I import that namespace+record I still get the same problem, am I missing something?

11:14 clgv: Morgawr: if you import the class correctly you can use the constructor

11:14 Morgawr: but you could also use the generated function (->MyRecord 1 2 3)

11:15 then you need no class import

11:16 Morgawr: clgv: ah.. I didn't know about ->MyRecord

11:16 thanks!

11:16 clgv: Morgawr: there is also a function map->MyRecord to convert maps to records

11:18 Morgawr: clgv: awesome

11:21 yedi: does github user ptaoussanis hang out here?

12:09 i have this middleware: https://www.refheap.com/85143

12:10 can someone explain to me why the mid uid: <different random number> is getting printed over 80 times?

12:10 why would that line of code be continually getting called

12:13 gtrak: because.. you're making a lot of requests?

12:13 more than you think?

12:19 yedi: heh yea, wtf...

12:19 oh maybe it's for all the static assets

12:22 paulfedorow: yedi: check the network tab in firebug or chrome dev tools, to see which requests are sent to the server

12:23 yedi: yea, it was the static assets i'm guessing... just forgot those were a thing

12:24 i guess i could change the middleware to only trigger on certain types of GETs based off the url resource it's getting

12:29 Morgawr: is there a map-indexed in parallel like pmap?

12:32 Glenjamin: it's lazy, so you should be able to combine them?

12:44 TEttinger: Morgawr: map-indexed isn't needed since you can do ##(print (map-indexed + (repeat 5 10)) " or " (map + (range) (repeat 5 10)))

12:44 lazybot: ⇒ (10 11 12 13 14) or (10 11 12 13 14)nil

12:49 Glenjamin: ,(pmap + (repeat 5 10) (range))

12:49 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

12:49 Glenjamin: heh, fair enough

12:54 shoepie: any ideas why my .nrepl-port wouldn't be created when running "lein repl"?

12:54 technomancy: shoepie: older leiningen version?

12:55 shoepie: technomancy: on 2.2.0

12:55 technomancy: try upgrading

12:56 shoepie: technomancy: ah, that was it. gracias

12:56 technomancy: np

13:00 shoepie: trying to get fireplace.vim and cljs to play nicely

13:11 rasmusto: shoepie: iirc fireplace + cljs is still a bit new

13:12 shoepie: oh, you're using :Piggieback ?

13:13 cbp: How can I delete a project on clojars_

13:13 ?

13:15 technomancy: cbp: unless sensitive material was leaked we like to keep clojars immutable

13:15 but I can delete something if it's important.

13:16 cbp: Not really I just changed groupId for 2 projects

13:16 technomancy: better to leave it, I think

13:16 if we ever have to do a security review, having fewer discrepancies makes it more likely that we'd spot a change that came from an actual attack

13:16 cbp: Okies

13:16 technomancy: s/if/when/

13:18 dbasch: technomancy: how often do you reindex clojars? I uploaded something two weeks ago and it doesn’t show up in search results

13:21 technomancy: dbasch: indexing happens upon deploy, but sometimes there are boogs

13:23 dbasch: technomancy: what are you using for indexing / searching?

13:24 technomancy: I'll initiate a reindex

13:26 cbp: Is it a big issue if pom/jar files are not signed?

13:27 dbasch: ok, now it shows up

13:27 technoma`: cbp: it means it's impossible for anyone using your lib to verify their build.

13:28 it's kinda crappy, but it depends on the context, who's going to be using it, etc.

13:28 right now verifying your build is not very common, which sucks

13:28 cbp: it's a bunch of compiled protocol buffers

13:28 which i separated from the actual library that uses them

13:28 technoma`: I guess a better question is why it's not signed

13:29 cbp: the library is signed though

13:31 technoma`: doesn't really matter; one unsigned library is as bad an ten from an attack surface area perspective.

13:31 nDuff: cbp, I'd suggest signing it if you can. The Java-ecosystem world is already quite good about that -- things don't get into Central unless signed -- and the more folks do likewise on the Clojars front, the easier it'll be to catch up.

13:32 cbp: Hmm. I guess I'll figure out signing once i push a new version

13:32 technoma`: basically my hope is that a few years down the line having unsigned jars will be like having libs that depended on monolithic contrib was a few years ago

13:32 nDuff: cbp, *nod*. Having a GPG key published and out on the keyservers will be necessary if you ever want to get something into Central as opposed to Clojars anyhow, and I really do hope that Clojars will make it mandatory in the not-too-distant future as well.

13:33 technoma`: something that may have sort of made sense at the time even though you knew it was technically a bad idea, and now it's pretty annoying to have to deal with the fallout of peoples' laziness.

13:33 shoepie: rasmusto: I haven't tried :Piggieback yet

13:34 rasmusto: shoepie: was reading this issue: https://github.com/tpope/vim-fireplace/issues/14

13:36 shoepie: rasmusto: yeah, that that this morning, too. Just now tried :Piggieback with no luck

13:36 Cannot read property "pr_str" from undefined

13:37 just calling (range 100)

13:37 * nDuff has been using LightTable for introspecting running CLJS, even if using a different editor for actually *writing* that same code.

13:39 nDuff: ...tried cider.el+piggieback, but it just got flaky too often. Might have been something I could fix (such as completion built for JVM-hosted Clojure trying to activate on CLJS), but LT has the advantage of providing an environment that Just Works, even if it's not all there yet as an editor.

13:49 gfredericks2: I thought that (clj-http.client/post "..." {:body {} :as :json}) was supposed to work

13:49 am I misremembering?

13:49 (it *will* work if I manually convert the data to json first)

13:59 Vinzent: What logging library can be used on both clojure and clojurescript sides?

14:10 SegFaultAX: Vinzent: Logging in js-land is pretty different from logging server-side.

14:13 nullptr`: goog.log is pretty similar to the jvm-side logging libs

14:18 Vinzent: SegFaultAX, I understand that.

14:18 nullptr, I mean same API, so I could use cljx to share code which uses logging.

14:29 nullptr: Vinzent: not sure how much https://github.com/clojure/tools.logging is used "in the wild", but seems to have a simple logging surface and different back end implementations

14:29 could probably extend that to goog.log without massive effort

14:46 Vinzent: nullptr, as far as I see from the source, its interface is implemented with macros, which means I can't extend and use it directly; anyway, it's a good starting point for writing a port I guess

15:04 amalloy: i guess vinzent is gone, but c.t.logging isn't based on macros. it has a few primitive functions, and then a bunch of macros that wrap those

15:26 sdegutis: Aha! Apparently my methods aren't being reloaded at runtime because they're methods on a long-lived object.

15:26 I should really stop using (deftype).

15:28 coventry`: What are you working on these days, sdegutis?

15:28 sdegutis: (runtime = development time using ring's reload-when-changed middleware, whatever it's called)

15:28 coventry`: like, for fun or work?

15:29 coventry`: Where ever the deftype issue is coming up, I guess. Just curious.

15:29 sdegutis: coventry`: Ah that's work.. it's a Clojure web app (cleancoders.com)

15:31 coventry`: Fun.

15:31 sdegutis: Excessively so.

15:35 dbasch: this is a mildly interesting article, but the code itself could be much better http://blog.shriphani.com/2014/05/01/consistent-hashing-in-clojure/

15:35 that random-take function, ugh

15:43 sdegutis: dbasch: how would you do it?

15:44 dbasch: sdegutis: for one, it only works with unique elements

15:44 sdegutis: I wouldn’t force the collection into a set

15:45 cbp: I haven't the slightest clue what the appstore is downloading it but its happily going over 2 gb now

15:45 sdegutis: cbp: wrong channel?

15:45 cbp: yes,,

15:45 sdegutis: #clojure-social?

15:45 cbp: sorry :-(

15:46 sdegutis: Just wondering.

15:46 I haven't been to #clojure in a while, I just don't know what the rules are these-days on off-topic discussions.

15:47 technomancy: instant beheading

15:47 clojurebot got an upgrade while you were gone

15:48 joegallo: ah, yes, well, the rules have gotten a little harsher. the punishment for off topic conversations is scaphism.

15:49 sdegutis: technomancy: is he now able to join other channels, ie #clojure-social?

15:49 nullptr: (def behead (partial drop 1))

15:49 jdeisenberg: joegallo: that sounds a bit harsh.

15:49 coventry`: That wikipedia page needs a not-safe-for-children warning.

15:49 technomancy: nullptr: hah!

15:49 sdegutis: not sure what the protocol is there

15:50 joegallo: coventry`: history generally isn't

15:52 cbp: any instances where IllegalArgumentException Key must be integer might occur?

15:52 besides ##([] :a)

15:52 lazybot: java.lang.IllegalArgumentException: Key must be integer

15:52 dbasch: sdegutis: here’s a (slightly) better random-take https://www.refheap.com/85148

15:53 sdegutis: at least it works for collections with repeated items

15:57 coventry`: The right way is probably to sample from the n-partitions of a roughly (count coll)-size set, and pull all the elements out at once.

15:57 melipone: hello friends!

15:57 How do i get the process wrapped in a future statement?

15:58 I am bringing up a server through Jetty and I want to stop it

15:58 dbasch: coventry`: not sure I follow

15:59 amalloy: dbasch: i'm not sure i would call that random-take better. it's awful in a different way

16:00 llasram: Is the goal just to sample without replacement?

16:00 amalloy: https://github.com/flatland/useful/blob/develop/src/flatland/useful/seq.clj#L149 is a good solution, imo, although if i could go back i'd write it as (lazy-shuffle coll) instead of (take-shuffled n coll)

16:00 dbasch: amalloy: for that particular case, I’d just to (take n (shuffle coll))

16:01 coventry`: Oh, yeah, that's a better awy.

16:03 llasram: There's also reservoir sampling, which has the benefit of not holding the head of the input sequence: https://www.refheap.com/85150

16:03 (although the sequence does still need to be finite)

16:04 amalloy: llasram: i don't see why that's eager. the reduce could easily be reductions, or just a recursive lazy-seq

16:05 dbasch: amalloy: that code counts coll twice

16:05 amalloy: dbasch: counting a vector is free

16:06 dbasch: amalloy: yes, just not lazy

16:06 amalloy: of course not. neither is yours

16:07 the output is lazy, but you have to be strict/eager in consuming the input

16:07 llasram: amalloy: I'm not sure I see the benefit... You could take a sample from a sub-sequence of length `n` by taking the `n`th `reductions` result?

16:08 dbasch: amalloy: anyway, I was just trying to get it to work. The original one was trivially broken.

16:08 amalloy: llasram: looking at it again, reductions isn't much of an answer. but just manual recursion is much better than the reduce

16:08 llasram: amalloy: How so?

16:09 Oh, you just think it would be clearer?

16:09 amalloy: llasram: say i have a million items, and want to sample a thousand of them. your reservoir-sampling means you don't hold the head of the million items, but you do hold the head of a thousand

16:09 (it's also clearer)

16:10 dbasch: if you had a million items, the most efficient way would be to do a limited in-place shuffle of the array until you get to N

16:10 llasram: I'll buy the clearer, but the algorithm needs to hold the entire sample in memory, so that any member of the sample-thus-far is eligible for replacement

16:11 amalloy: yeah, i guess i'm not reading the algorithm very well

16:11 you soak up the first N items from the input, and then for anything left you decide randomly whether to replace one of those originally-selected items

16:12 so you need them all

16:12 dbasch: amalloy: I mean fisher-yates, except you stop at 1000 or whatever

16:13 amalloy: dbasch: that's what my take-shuffled does

16:14 dbasch: amalloy: as far as I can tell, you’re not doing anything in-place

16:15 amalloy: i'm assoc'ing the input vector, which is as in-place as anything functional is

16:15 dbasch: amalloy: but then it’s not fisher-yates, which obviously is not functional and more efficient for large collections :P

16:16 amalloy: dbasch: i disagree that it's not fisher-yates

16:16 just because it's often implemented with mutation doesn't mean the algorithm is innately mutation-based

16:18 eg, the wikipedia page says "exchange a[i] and a[j]". who says that means mutating an array?

16:18 jdeisenberg: The original algorithm (as described in Wikipedia) appears to use an original list and a new list.

16:18 amalloy: indeed

16:18 jdeisenberg: That lends itself a bit more to a functional approach, yes?

16:18 dbasch: amalloy: I mean that the most efficient way is to mutate an array, obviously

16:19 amalloy: dbasch: so why are you using clojure? c is more efficient. we make tradeoffs all the time

16:19 jdeisenberg: it does. i hadn't read that version before just now, but that's an interesting way to look at how my vector version works

16:19 dbasch: amalloy: I had to solve this exact problem for billions of urls years ago, and I did it in c

16:20 r00k: Anyone ever seen some weirdness with ring & wrap-params where sometimes integers submitted through a form come in as chars?

16:20 amalloy: r00k: they're coming in as strings, and you're seq'ing over them somehow

16:21 r00k: amalloy: That does seem the likeliest thing...

16:21 jdeisenberg: I wrote a solution in Erlang using that algorithm; http://chimera.labs.oreilly.com/books/1234000000726/apa.html#_literal_cards_erl_literal_2

16:21 r00k: I'll double-check that.

16:22 jdeisenberg: or rather, added comments to the source from Literate Programs

16:22 coventry`: dbasch: amalloy: Could take-shuffled be sped up with transients? If not, actually seems like a good candidate for bashing a local array.

16:27 juliobarros: Any know if there is a Quill like library for drawing on a browser canvas?

16:33 r00k: amalloy: You were totally right. Thanks!

16:35 Is there a more idiomatic way to accomplish (defn fooify [xs] (if (coll? xs) (map bar xs) (bar xs))) where xs can be strings?

16:35 More specifically, where xs can be either ["baz"] or "baz"

16:36 jcromartie: r00k: I've written something like this a few times

16:36 amalloy: r00k: make it always be a list, and then always use map on it

16:36 jcromartie: r00k: (defn foo [x] (if (coll? x) x (seq x)))

16:36 err

16:36 no

16:36 s/seq/list/

16:37 amalloy: there's not much use propagating the "string or list of strings" dichotomy to more code who will have to cope with it

16:37 r00k: amalloy: Is there a handy fn to make something a list but only if it isn't one already? (won't increase nesting I mean)

16:37 jcromartie: but it's probably a bad pattern

16:37 llasram: (inc amalloy)

16:37 lazybot: ⇒ 105

16:37 llasram: That pattern has only ever caused me pain

16:37 r00k: amalloy: Also, my example was wrong. I am always returning a list. The else branch was (vector (bar xs)).

16:37 amalloy: yes. it's a shame compojure's param middleware does that, but on the other hand it's much more convenient than the alternative

16:47 technomancy: HTTP headers being case-insensitive multimaps is a weird design to begin with

16:48 jdeisenberg: juliobarros: see http://www.chris-granger.com/projects/cljs/ specifically, "monet" -- this is a clojureScript thing.

16:49 amalloy: technomancy: i don't think it's the headers that are at issue, so much as the query-params

16:49 jdeisenberg: juliobarros: followed it to https://github.com/rm-hull/monet

16:49 technomancy: amalloy: oh, gotcha

16:50 juliobarros: jdeisenberg: Cool. Thanks. I'll take a look at that.

16:50 amalloy: are headers really multimaps? i can't think of an example

16:50 jdeisenberg: Doesn't seem very quil-ish, though :(

16:50 technomancy: jdeisenberg: quil is pretty imperative; I wouldn't necessarily hold it up as a paragon of functional api design.

16:51 jdeisenberg: technomancy: Is there a good functional-graphics-with-ease-of-Processing type module for Clojure?

16:52 technomancy: jdeisenberg: the best functional graphics API I know of is Racket's. I don't know of any in Clojure that I'd recommend.

16:52 that is, I would recommend *using* Quil, but I wouldn't recommend copying it's design.

16:53 jdeisenberg: Ah, OK. Thanks. I teach Processing as intro to programming, and was thinking of moving over to Quil.

16:54 technomancy: it's definitely lots of fun

16:54 a lot more fun than Processing sounds =)

17:01 TerranceWarrior: how would your normally handle error passing up the stack chain in clojure?

17:01 also every thing is passed by referene?

17:07 coventry`: I handle it by reading the resulting stack trace and squashing the bug. :-) Things are passed by reference, but that doesn't make much difference for most objects, since they tend to be immutable.

17:11 TerranceWarrior: coventry`: ah ok. how do you 'read' it. with 'try'?

17:26 `szx: jdeisenberg: canvas API is pretty easy, as easy as processing IMO

17:26 scape_: does loop-recur work similar to trampoline?

17:27 `szx: TerranceWarrior: i think coventry` was talking about debugging stack traces, not exception handling which i think was what you were asking about?

17:27 amalloy: scape_: errrr. trampoline is implemented via loop/recur. it's not clear what your question wants to know

17:27 scape_: just how/if theyre related

17:27 thx, that explains it

17:32 TerranceWarrior: `szx: i am asking about how to handle errors in code and whether to pass them up the call chain.

17:32 sdegutis: I am about to use (partial) to solve a problem.

17:32 This would be impossible in a lesser language.

17:32 TerranceWarrior: TEttinger3: thanks.

17:32 `szx: TerranceWarrior: you could return nil, or throw an exception and catch it

17:33 coventry`: ,(try (throw (Exception. "I'm an exception")) (catch Exception e (throw e)))

17:33 clojurebot: coventry`: Pardon?

17:33 `szx: heh

17:38 sdegutis: Never mind, partial alone will not solve it.

17:39 TerranceWarrior: `szx: right ok. but i know that handling exceptions you pay hevily in performance.

17:41 amalloy: partial is at best a partial solution, sdegutis

17:41 sdegutis: amalloy: Very good joke.

17:42 `szx: TerranceWarrior: not sure what's the current state of the JVM in regards to that, but i'm pretty sure that the common wisdom is that exceptions are there for exceptional cases only, and therefore shouldn't have a significant impact on performance

17:42 i.e. you shouldn't use exceptions for control flow

17:43 TerranceWarrior: `szx: AFAIK there is a call check and possibly more within each function of a try block.

17:44 `szx: TerranceWarrior: https://groups.google.com/forum/#!topic/clojure/kOrg9XCYklQ for Rich Hickey's take

17:56 sdegutis: Should be used (partial f arg1) or #(apply f arg1 %&) ?

17:56 Bronsa: sdegutis: go with partial

17:57 sdegutis: I will test it in the REPL to ensure that it respects dynamic changes in the applied function's source code.

18:01 Aww, no! It does not work. When I do (partial) it captures the definition of the function at this time. I will perhaps use sharpquine to capture the var instead.

18:02 This works better. But now I will test it with %&

18:03 With (apply %&) I do not have to use sharpquine, it captures the fresh var at each call.

18:03 This is a trade-off.

18:04 gtrak: it's not apply that's the issue, it's #(apply f ..)

18:04 same effect #((partial f ...) %&)

18:05 DerGuteMoritz: shouldn't (partial #'f) work? in case f is a var, that is

18:05 amalloy: yes, DerGuteMoritz

18:05 sdegutis: gtrak: I don't understand what you said.

18:05 gtrak: sdegutis: the deref happens when the anon-function is run.

18:06 sdegutis: gtrak: I have done (partial #'myfunc state) and #(apply myfunc state %&) and both work.

18:06 gtrak: partial derefs the var when it evals its args, like any normal function.

18:06 PigDude: is there something besides map for iterating two collections in parallel? other things like for and doseq create cross-products

18:06 fowlslegs: What is the best way to test whether one piece of code or another works faster? My immediate thought is to run the task #'repeatedly, say a few hundred times, with randomized input variables, wrapping both of the snippets in #'time, and taking the better. I'm not very knowledgeable on how Clojure/ Java handles memory allocation, garbage collection, etc. though, so I'm not sure if this is the best way to go about doing this.

18:06 PigDude: er, is there a `domap`, so to speak

18:07 sdegutis: gtrak: so what are you saying, that I should use partial?

18:07 gtrak: I'd try to find a way to avoid depending on the timing of var-capture :-), I guess, is the point, that doesn't have to be a visible tradeoff in most cases.

18:07 I don't know what your code is doing.. so I'm just generalizing.

18:08 I think partial's prettier than #(..) when it's straight-forward.

18:08 dbasch: fowlslegs: criterium

18:09 fowlslegs: https://github.com/hugoduncan/criterium

18:09 sdegutis: gtrak: I have a few functions that I want to act on some state, and I want them all to reload when I reload my file while developing live.

18:09 fowlslegs: Thanks dbasch!

18:10 TerranceWarrior: PigDude: Did you see Lando's Fan on utube?

18:10 `szx: Setting a 'dynamic' variable? Ha, thats the kind of hack Python uses, global vars.

18:12 sdegutis: Look: https://gist.github.com/sdegutis/7c4aa63d7abb5180caf2

18:13 I just want it so that when I change one of those first two functions, anyone who already called (create-names-fns-map) and stored the result, they can have their state remain the same, yet the function differs.

18:14 Say someone stores (create-names-fns-map) into 'foo, now when they do ((:add-name foo) "gtrak") I wish for that to continue working, even after they add some code to (add-name) and reload the file it lives in.

18:14 Yes, Now you see my question clearly.

18:14 gtrak: sdegutis: ah, I get it.. but.. why?

18:15 PigDude: TerranceWarrior: hm? what's that

18:15 gtrak: it looks suspiciously like an object.

18:15 sdegutis: gtrak: You see, I want to make sure that when I reload my files, my new functions are used with conjunction with the old state.

18:15 gtrak: I have some state that is setup one-time with ring's "init" feature and that state I don't want to reload at every file-reload.

18:16 gtrak: well, that can be solved by defonce.

18:16 TerranceWarrior: PigDude: A Key and Peel sketch with reference to 'PigDude' in a tiny Star Wars spoof.

18:16 `szx: TerranceWarrior: keep in mind this post is from 2008, a lot has changed since so current thinking might be different

18:17 sdegutis: gtrak: that seems irrelevant in this case.

18:17 gtrak: For you see, the state must be stored at the same time the functions are defined. And the functions may be swapped out for "mock" functions during a test-suite-run.

18:17 gtrak: sdegutis: I'd just pass the state around and have folks call the functions. destructuring a map to get functions is something I've considered many times before and thrown out.

18:18 or define a protocol on the service, and have people call into that using an impl of the service.

18:18 sdegutis: gtrak: that was my initial solution, using a protocol and deftype for each implementation.

18:19 But you see, they have the very same problem. The new functions aren't used whenever you reload the file where they're defined!

18:19 This makes sense, because the instance isn't going to change just because the factory function (the deftype body) that created it has changed.

18:20 It's not loosely coupled, it's tightly coupled to the body.

18:20 gtrak: I'd rather have an extra convenience function to take care of this than change an api for dev-use convenience.

18:20 rip the state out of the record, call the new record constructor with it.

18:20 after its redefined.

18:20 it's.

18:21 or, don't inline the function definitions, extend-type doesn't have this problem.

18:21 that's probably your best bet.

18:22 know what I mean?

18:23 re-evaling an extend-type/protocol form will redefine the global map of impls, should work for old instances.

18:24 the tiniest bit slower than inlining it

18:25 sdegutis: That sounds great.

18:25 gtrak: phew :-)

18:25 sdegutis: But still, I think this should be redesigned to just use plain old functions.

18:25 gtrak: but.. then you're writing javascript.

18:26 or you mean not the map-of-functions, but ns-functions.

18:26 sdegutis: I don't know how I plan to distribute the functions yet.

18:44 Oh no, I cannot just pass the namespace that contains the functions.

18:44 They are not first-class things. Although I can pass the symbol.

19:48 upwardindex: Is it possible to set the name of the thread created by a future (so that jstack are clearer)?

19:50 amalloy: upwardindex: no. future doesn't even guarantee to create a thread; it may reuse one it finds lying around

19:50 if you want more control, create the thread yourself

19:50 AWizzArd: and there you can use setName

19:50 upwardindex: amalloy: ok, thanks!

19:50 AWizzArd: http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

20:01 danneu: https://news.ycombinator.com/item?id=7700638

20:02 storme: haha nice

20:02 tuft: haha

20:18 PigDude: ! i'm calling (ns/f) from within same-named function 'f' in another ns, but i get bad arity, as if it's calling local fn?

20:19 amalloy: &((fn inc [] (clojure.core/inc 1)))

20:19 lazybot: ⇒ 2

20:19 amalloy: seems to me like it works fine, PigDude. do you have an example you can put on refheap or something?

20:26 PigDude: amalloy: it feels like anything could be broken w/ some of these error messages, i guess it was not that

20:27 amalloy: PigDude: i bet if you put your stacktrace on refheap, someone could tell you what's wrong

20:31 ughhhh, i was looking through the source of a library i was evaluating, and i see here (distinct (vec (flatten (map keys ...))))

20:33 hiredman: :(

20:33 it's like people don't even care

20:36 PigDude: why does this happen?

20:36 hiredman: https://github.com/search?q=%22%28distinct+%28vec+%28flatten+%28map+keys%22&type=Code&ref=searchresults

20:36 PigDude: &(filter (partial > 4) (iterate (partial * 2) 1))

20:36 lazybot: java.lang.ArithmeticException: integer overflow

20:37 PigDude: i expected this to be [1 2]

20:37 amalloy: PigDude: well, you tried to print an infinitely long list

20:37 PigDude: but i have filtered the list

20:37 amalloy: you've filtered it, but you haven't *stopped* it. clojure doesn't know for sure that the millionth item in the list is 3

20:38 that is, it doesn't know the numbers are increasing and your predicate will never go back to returning true

20:38 PigDude: so is there a form for this or do i have to recur?

20:38 amalloy: &(doc take-while)

20:38 lazybot: ⇒ "([pred coll]); Returns a lazy sequence of successive items from coll while (pred item) returns true. pred must be free of side-effects."

20:38 PigDude: ah, thanks

20:56 yeoj___: hi, is there anyway in emacs to automatically create test files with the correct namespace stub/etc? does cider/clojure mode would have provided that somewhere?

20:58 amalloy: do you create test files so often that having the ns form provided would be a substantial win? i mean, time-saving features are nice, but i sure don't do it often enough that i'd have thought to ask

20:58 yeoj___: amalloy: i'm just rethinking my workflow, and as i'm interacting with a function i'm defining i'm constantly jumping back and forth to the test file

20:59 amalloy: maybe i should be spending more time at a repl instead of the test file

21:01 gfredericks: yeoj___: jumping back and forth isn't the same thing as creating a new file

21:01 jumping back and forth is supported in cider for the *-test naming convention

21:02 yeoj___: gfredericks: ok sounds good. i was just thinking something would write the namespace/etc for me because it's pretty much always the same, and refer/use the stuff i'm testing, etc.

21:02 gfredericks: i thought emacs live did that for me but i don't remember, maybe not.

21:06 cespare: Thoughts about carmine? Anyone use other clients (maybe just jedis?)

21:10 lvh: Hi

21:10 I'm trying to wrap my head around Korma, and I'm not seeing where the column definitions would go

21:10 none of the defentities seem to define, say, that there exists a thing called a "username" and that it is a string and a user has one

21:11 which I guess is fine as long as korma never tries to produce DDL statements?

21:12 kenrestivo: you might want to try honeysql or the other alternatives

21:18 lvh: Sorry, got disconnected.

21:18 Did anyone say something in the mean while?

21:23 akurilin: Do we have any libraries in clojure that do fuzzy string matching? e.g. make sure that every character in the search-term is present in the string in that specific order?

21:24 or actually, I think we have a couple. Is there one you guys are happy with?

21:46 Nvm didn't find what I was looking for, just wrote it myself.

22:13 mgaare: lvh: korma is somewhat high in magic. I've been playing with sqlingvo lately and I would recommend giving it a look

22:27 lvh: by the way, I was walking through the datomic tutorial and saw expressions like these: @(d/transact conn data-tx)

22:27 I know @ means "deref" but what is the point of derefing the result of the transact call? does it have some kind of side effect?

22:27 (it's not assigned to anything or whatever)

22:30 amalloy: it probably returns to you a promise or delay or something, representing the plan to eventually transact

22:30 not that i know a lot about datomic

22:30 AWizzArd: Perhaps the returned object is indeed a promise and will signal you that the transaction has finished, if you care.

22:31 dbasch: transact does return a future http://docs.datomic.com/clojure/#datomic.api/transact

22:32 lvh: oh, cool. thanks :)

22:33 AWizzArd: Ah yes, we got it.

22:33 That way you can blockwait in your thread until the tx has finished.

22:37 KeithPM: Good evening clojurists. Can someone explain to me the significance of the '- 'in (set! (.-x point) 15) the following gist? kpmaynard / gist:43500393959b3615a3fe … Thanks

22:40 dbasch: KeithPM: I can’t see the gist, but “-“ is used in clojurescript to access js properties

22:41 AWizzArd: class Point { int x, y } => then you have a (def my-point (Point. 10 20)) Now (.-x my-point) ==> 10

22:41 dbasch: “.-“ actually

22:41 KeithPM: Oh OK… This property was a java instance variable

22:41 AWizzArd: JavaScript maybe. I guess your code snippet is a ClojureScript one.

22:42 KeithPM: No actually it was clojure..

22:44 -https://gist.github.com/kpmaynard/43500393959b3615a3fe Gist is here, sorry.

22:46 AWizzArd: Well okay, it still looks like a field accessor.

22:46 a place

22:47 TEttinger: is it accessing a variable called _x ?

22:47 no, nvm

22:47 KeithPM: No x

22:49 beamso: the code in the gist worked for me :/

22:49 AWizzArd: Which beamso? The first or second?

22:49 Strange that this operator isn’t listed at http://clojure.org/java_interop

22:49 KeithPM: The first one fails

22:50 beamso: AWizzArd: the code in the gist looks identical to me in both cases

22:51 AWizzArd: beamso: on my computer the version at the bottom is different

22:51 it is rendered .-x vs. .x

22:51 KeithPM: No just the '-' is the only difference… see the commented line

22:51 beamso: oh, the .-x

22:51 the top one worked

22:51 KeithPM: Really?

22:51 AWizzArd: In Clojure I would have expected the top one to work.

22:52 cljs however indeed has this .- accessor

22:52 beamso: i'd never seen set! used in that manner but i haven't done interop with public fields in java yet

22:53 KeithPM: Found it in Fogus' book.

22:53 AWizzArd: I can’t remember to have ever seen it for Clojure before, but maybe it was indeed introduced in some version.

22:57 KeithPM: OK. I think I upgraded to 1.6 tonight because I could not find set! in light table

23:33 amalloy: AWizzArd: .-x was added to clojure when it was added to cljs, which i think was 1.3, maybe 1.4

23:34 those should both work in any non-cljs version of clojure i know of, though

23:35 ,(.x (java.awt.Point. 1 2))

23:35 clojurebot: 1

23:36 amalloy: ,(set! (.x (java.awt.Point. 1 2)) 3)

23:36 clojurebot: 3

23:38 KeithPM: Hmmm… Maybe it is not working with the bound value 'origin'? Let me try your suggestion amalloy

23:40 Works fine anonymously but fails once the point is assigned to a named value

23:45 TEttinger: Morgawr: how's cloister coming along?

23:59 amalloy: ,(let [p (identity (java.awt.Point. 1 2))] (set! (.x p) 3))

23:59 clojurebot: 3

23:59 amalloy: still works fine, KeithPM

23:59 maybe you don't actually have a Point anymore

Logging service provided by n01se.net