#clojure log - May 31 2012

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

0:00 amalloy: (even though it claims to). and you installed 0.3.0, which is the lein2 plugin, not the lein1 plugin

0:01 coventry: Just a misunderstanding, will give it a go. Thanks.

0:04 Ah, so that's why adding the plugin to ./lein/project.clj didn't work.

0:32 michaelr525: morning!

3:01 tomoj: devn: hey, do you still have the link to that gist about core.logic?

3:02 my laptop conveniently locked up completely right as I was going to click on it, thinking "whoa"

3:02 and google custom search seems not to have picked it up yet

3:03 oh

3:03 datomic not core.logic

3:03 found it

3:21 muhoo: where is it?

3:35 oic, i had to do this before i finally understood it: (->> [185 13235209671M 25939708511M 1654794401M 12429901063M 131081 65539] (mapcat #(cons "\n" (next (map {\0 \ , \1 \#} (Long/toBinaryString %))))) (apply str) symbol)

3:35 it's a bitmap, clever.

4:35 TEttinger: hmm

4:35 I'm trying to make a dead-simple Conway's Game of Life in the console

4:36 ordnungswidrig: TEttinger: that is a good excercise

4:36 TEttinger: and I can't figure out how to keep the app going, continually generating new boards

4:36 it is something to do with Thread/sleep

4:36 ordnungswidrig: should it repeateldy print the state in the repl?

4:37 TEttinger: I just need to know a way to evaluate some function, sleep, eval, sleep, etc.

4:37 well it could use a repl?

4:37 i was just using lein run

4:37 i used the repl for the development part

4:37 ordnungswidrig: k

4:38 can you show your problem at a pastebin?

4:39 clgv: TEttinger: you just need an infinite loop that prints one iteration step.

4:40 maybe you should specify in advance how many steps you want to see ;)

4:40 TEttinger: e.g.: (dotimes [_ 100] (my-iteration-code))

4:41 PeregrinePDX: (take 10 (repeatedly game-of-life-function))

4:41 Would get you 10 iterations.

4:42 TEttinger: thanks

4:43 ordnungswidrig: for a pure implementation you can do like this:

4:43 TEttinger: I was struggling with ideone having weird syntax highlighting, and that made me think there was a problem with my code

4:43 http://pastie.org/4000414

4:44 ordnungswidrig: (->> step-fn (repeat num-iters) (reduce #(%2 %1) seed))

4:45 TEttinger: ->> does what now?

4:46 ordnungswidrig: (->> 5 (+ 1 2 3) (print "result" )) will expand to (print "result" (+ 1 2 3 5)) thus is "inserts" the result as the _last_ argument to the next expression

4:46 TEttinger: PeregrinePDX, yeah the code i based it off of (mislabeled in there, part of -main is the original code)

4:46 ordnungswidrig: but it was overly complicated because iterate will be easier

4:46 TEttinger: yeah the code originally used iterate

4:47 ordnungswidrig: so (nth (iterate step seed) num-iters) will be easier

4:47 TEttinger: I'm sorry, what?

4:48 what is that solving?

4:48 ordnungswidrig: this will to the same as the code I showed above using reduce

4:48 clgv: probably `take` is better since you want to see the progress of the game, right?

4:48 TEttinger: yeah

4:48 but I need to pause with Thread.sleep between printing the steps

4:49 ideally it would keep going until the user Ctrl-D or Ctrl-C 's it

4:49 PeregrinePDX: So remove the take x portion.

4:49 ordnungswidrig: PeregrinePDX: there is no printing

4:50 TEttinger: yeah, but how would I sleep

4:50 clgv: (Thread/sleep 1000)

4:51 TEttinger: steps it needs to do: run first generation, print, sleep, run second generation, print, sleep...

4:51 clgv: &(do (println "1") (flush) (Thread/sleep) (println "2") (flush))

4:51 lazybot: java.lang.NoSuchFieldException: sleep

4:51 TEttinger: &(do (println "1") (flush) (Thread/sleep 10) (println "2") (flush))

4:51 lazybot: ⇒ 1 2 nil

4:51 clgv: ah lol^^

4:52 TEttinger: so how would i handle function calls mixed into taking an element from a lazy sequence

4:52 clgv: TEttinger: (doseq [board (iterate ...)] (println board) (Thread/sleep 1000))

4:53 TEttinger: oh! doseq! I always forget about the do??? functions

4:53 thanks clgv, will try

4:53 clgv: you want to have side effects, you should use a `do*` ;)

4:59 TEttinger: http://pastie.org/4000482 for those who want to try, it needs an 80-char-wide terminal

5:45 amalloy: TEttinger: have you looked at http://www.4clojure.com/problem/94?

6:21 opened: I'm going to start reading sicp. Any comments on the book, from the clojure perspective?

6:22 clgv: amalloy: that one is underspecified for the "edge cases" ;)

6:25 ejackson: anybody know the equivalent for $(this) is cljs ?

6:26 (using jayq, that is)

6:26 clgv: ejackson: maybe an implizit 'this symbol?

6:27 *implicit

6:27 ejackson: yeah, I fooled about with ($ "this") and ($ :this) etc

6:28 (js* "this") yields DOM objects in callback, but is a bit wild

6:31 clgv: ejackson: did you examine the js it is compiled to?

6:31 ejackson: eep, no I didn't, good call, thanks !

6:34 lol its 20k lines

6:34 hence all the fuss about minifiers :)

6:37 FTR, this works: ($ (js* "this")) in callbacks to get a jquery on that thingie doing the calling

6:37 kilon: never liked any of the common lisp / scheme books i read

6:37 ejackson: a bit wild though

6:37 kilon: confused me a lot

6:37 fortunately clojure documentation is way better

6:38 i find this very helpful

6:38 http://clojuredocs.org/quickref/Clojure%20Core

6:38 clgv: ejackson: if you are interested you could trace back through jayq where ($ :this) fails. would be worth a patch I guess.

6:39 kilon: this is also pretty good: http://clojure.org/cheatsheet - I have the pdf printed on the desk ;)

6:40 kilon: clgv: indeed this is extremely helpful

6:41 thanks , missed that one

6:41 i am suprised that such a new language has such good documentation

6:45 ejackson: clgv: I'll raise it, but I'm sure there's a reason its not there already :)

6:45 Raynes: you're a contributor - you still about ?

6:46 clgv: ejackson: which reason would that be?

6:46 ejackson: something like "yes it works in your instance, but look at this other case where it blows up"

6:46 i don't know enough about the JS world to say

6:48 clgv: then I would start with the premis that this one might have slipped attention so far since cljs and jayq are both pretty young ;)

6:49 ejackson: alrighty, I'll raise an issue and see who slaps me up first :)

7:13 clgv: Instead of having global parameters for the run of an algorithm, which are accessed where needed, one could compile the functions of the algorithm when just before the run and inject the parameters as constants into the code of the functions. One could write a special defn-macro for this. Has anyone tried that yet?

7:15 ejackson: sortof like inlining data

7:17 clgv: ejackson: and functions. I'd describe it more as templates for functions

7:17 ejackson: what's the win ?

7:17 clgv: The functions would get cleaner since I dont have to pass the Parameter-Container along and access it to query the parameter values

7:19 ejackson: you can't have the data as argument 0 and partial it in ?

7:19 clgv: jvm could inline functions (that are given as parameter as well)

7:19 ejackson: it's distributed through the whole algorithm

7:19 ejackson: yeah, I have similar stuff but I like it there :)

7:20 so I can see its bony ass

7:20 clgv: I dont like it - I would like more clarity and save the additional parameter access times

7:21 I have a single point where I could compile the whole thing

7:22 maybe it could even be dual: if no parameters are bound it compiles normal functions that take the parameter-container

7:23 ejackson: i've grown to be frightened of such magics

7:24 clgv: it needs to be thouroughly tested. thats true. but it can't really cause much pain since it'll explode if no params are bound ;)

7:26 a pity that the word "template" is so strictly bound to html if you search for "clojure function templates"

7:27 hmmm there is clojure.template but thats not sufficient

7:27 and not really near the vision I have

7:30 michaelr525: can i create a non-caching lazy seq using loop recur? I would like to "run over" the rows of a big table, proccesing one at a time.

7:31 * kilon wonders how an OS in clojure would be like

7:35 Chousuke: michaelr525: just use a lazy seq and doseq

7:37 michaelr525: Chousuke: isn't there a potential stack overflow?

7:37 Chousuke: no?

7:37 clojurebot: no is tufflax: there was a question somewhere in there, the answer

7:37 michaelr525: Chousuke: i mean, lazy-seq implies recursive function call which implies stack overflow, no?

7:38 Chousuke: nope

7:38 laziness prevents the stack growth

7:39 michaelr525: are you sure? i will eventually force the whole seq

7:40 say 2M items, means 2M recursions no?

7:40 Chousuke: ths recursive call is done when an element is realised, at which point the previous call will have returned

7:40 sjl: michaelr525: as long as you don't hold onto a pointer to the head of that seq, the elements will get garbage collected as you move past them

7:40 michaelr525: great! :)

7:40 Chousuke: that is a separate issue

7:41 clgv: kilon: slow. see solaris ;)

7:41 sjl: yeah, there's not really any recursion because by the time you actually call the function a second time you're out of the first call

7:41 kilon: clgv: i dont mean entirely, linux kerner will do

7:42 keep around things in C for speed, is perfectly fine by me

7:43 clgv: kilon: isnt solaris a unix with only a java desktop?

7:43 kilon: it is ? sorry i am not that familiar with it

7:43 never used it

7:43 clgv: I had a demo cd back in 2004 or so ;)

7:44 scottj: kilon: I don't think clojure dictates much of how a user environment would be. you could imagine the concurrency and database-backed filesystem of BeOS (but with datomic), the interactiveness of smalltalk VM/Symbolics Genera/emacs, but maybe you'd just end up with unity running the speed of libreoffice.

7:45 kilon: one thing i learned , is making a coder life easier, immediately affects the user

7:47 look how much python boosted the development of linux

7:48 pupy linux uses both genie (python clone that runs much faster, with static types) and Vala (C# clone)

7:49 cant say either have any noticable slow downs

7:49 and python is way way slower than clojure

7:49 michaelr525: (defn rows [start-at limit]

7:49 (lazy-cat (get-rows limit start-at) (rows limit (+ start-at limit))))

7:50 does this look ok ^^^

7:51 i mean, it doesn't hold onto it's head, does it? ;)

8:00 wow

8:00 it works

8:00 so cool..

8:02 err

8:02 how to stop?

8:02 hehe

8:04 kilon: reboot always works :D

8:05 michaelr525: maybe take-while

8:09 if lazy seq doesn't recurse, why do we need loop recur?

8:11 ejackson: for data not dealing with seqs :)

8:12 michaelr525: such as..

8:14 ejackson: a numeric function: such as say an integration

8:14 michaelr525: (defn rows [limit start-at]

8:14 (lazy-cat (get-rows limit start-at)

8:14 (rows limit (+ start-at limit))))

8:14 why take 1 from the above triggers infinite realization?

8:16 bobry: how can I tell cljsbuild to include a js library in the output file?

8:16 ejackson: bobry: i dunno, i tend to put it into the HTML template

8:17 michaelr525: depends on get-rows i guess

8:17 bobry: yup, that'll surely work :)

8:17 I thought it has :externs option, but I can't find it in the docs

8:17 ejackson: luke vanderhart's articel goes into this, 1 sec

8:18 here: http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html

8:19 michaelr525: ejackson: err how does it depend on get-rows? the whole thing seems very lazy to me

8:19 ejackson: well, I dunno what get-rows is/does, it might realise the whole thing

8:20 bobry: ejackson: thanks! that's exactly what I needed :)

8:20 michaelr525: ejackson: it returns a vector of maps (rows from database)

8:21 ejackson: hmm, dunno.

8:22 michaelr525: oh, maybe the repl does automatically?

8:24 ejackson: chunking perhaps

8:24 michaelr525: ah

8:24 yeah, it could be

8:24 damn chunking

8:26 ejackson: ah

8:27 michaelr525: not chunking i think, i replaced get rows with the following and it works as expected now: (defn get-rows [row-limit start-at] [1 2 3])

8:31 ejackson: it happens when get-rows returns an empty seq

8:32 ejackson: how do you explain that?

8:34 ejackson: dunno

8:34 :)

8:35 michaelr525: &(lazy-cat [1 2 3] [0])

8:35 lazybot: ⇒ (1 2 3 0)

8:36 michaelr525: &(lazy-cat [1 2 3] [])

8:36 lazybot: ⇒ (1 2 3)

8:36 michaelr525: &(lazy-cat [] [])

8:36 lazybot: ⇒ ()

8:36 michaelr525: &(defn get-rows [] nil)

8:36 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

8:36 clojurebot: Roger.

8:39 michaelr525: &(let [f1 (fn [] nil) f2 (fn [] (lazy-cat (f1) (f2)))] (take 1 (f2)))

8:39 lazybot: java.lang.RuntimeException: Unable to resolve symbol: f2 in this context

9:01 Chiron_: Hi, (defn fun [id & {:keys [name phones]}] (println name) (println phones)) phones is a varargs . it could be one value or a lot of values . should I destructure it somehow also?

9:11 mfex: Chiron_: phones can't be both a keyword argument and a varargs. You should pass it a collection if you more than one value for phones

9:23 rguillebert: hi

9:24 is there something equivalent to the haskell "where" clause in clojure ?

9:27 jedmtnman: rguillebert: cond, maybe?

9:27 ,(doc cond)

9:28 clojurebot: "([& clauses]); Takes a set of test/expr pairs. It evaluates each test one at a time. If a test returns logical true, cond evaluates and returns the value of the corresponding expr and doesn't evaluate any of the other tests or exprs. (cond) returns nil."

9:28 jedmtnman: or

9:28 ,(loop)

9:28 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (0) passed to: core$loop>

9:28 jedmtnman: ,(doc loop)

9:28 clojurebot: "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein. Acts as a recur target."

9:29 mfex: rguillebert: use (let or (letfn. for both of these the declarations come for their usage, in haskell the declarations in the 'where' are after their usage

9:39 rguillebert: mfex, yes I think that'll do it

9:39 thanks

10:25 glitch99: this is kind of a goofy question - don't know if anyone is in the room - what is the typical clojure/lisp coding style - lots of _ like C? lots of camel case like java and C++? hungarian?

10:25 babilen: glitch99: typically-like-this

10:25 glitch99: lowercase and dash?

10:26 babilen: glitch99: Yes. See http://clojure.github.com/clojure/ for a list of functions in the standard library

10:26 bsteuber: yes except java casing for java interop

10:26 di-csuehs: that is an interesting question...I don't recall seeing a style guide.

10:27 glitch99: awesome :-) thanks everyone!

10:27 babilen: di-csuehs, glitch99: http://dev.clojure.org/display/design/Library+Coding+Standards

10:27 Vinzent: bsteuber, actually it's not only java interop - any type names should be CamelCased

10:29 babilen: ... as should names of protocols (i.a.)

10:34 twhume: So… I'm trying to load Java classes from an array of bytes (being a serialised class) in Clojure. I also need to be able to unload classes, which I think means getting the class loader which loads them garbage-collected. There may be an easier way of doing this than the one I'm trying, which is to gen-class a subclass of ClassLoader and use that. I'm having trouble with gen-class though: I can generate a class OK but it always seems to

10:34 subclass Object, and not respond to dot-notation method calls.

10:34 https://gist.github.com/2843627 has the code - (-dummy cg) works just fine, (.dummy cg) doesn't...

10:35 Any ideas?

10:41 llasram: twhume: Clojure >=1.3 includes a class-loader which may already do what you need. It's used by deftype but gen-class wasn't switched over. https://github.com/clojure/clojure/blob/eccde24c7fb63679f00c64b3c70c03956f0ce2c3/src/jvm/clojure/lang/DynamicClassLoader.java

10:42 It's wired in to how Clojure loads classes, with some helpers available on clojure.lang.RT

10:43 Here's as example I wrote, extending gen-class to use DynamicClassLoader: https://github.com/llasram/shady/blob/master/src/shady/gen_class.clj

10:43 gfredericks: what's the latest strategy for cljs testing?

10:44 twhume: Thanks. I'm quite a Clojure noob, mind if I have a look at that and probably get back to you with more questions?

10:44 llasram: np

10:47 wastrel: hi

10:50 TimMc: dnolen: Ever seen anything like this with core.match? https://www.refheap.com/paste/2937

10:51 dnolen: Basically, a match clause is intermittently returning nil, even though it is guaranteed a match.

10:55 SurlyFrog: Hi all, I'm coming to Clojure without any significant Java experience (a decade or so C, Common Lisp, Python, and a few others). I'm wondering if the JVM handles "swapping" or caching large data structures to disk. For example, if you are growing a large data structure in memory, and it gets too large, will the JVM automagically cache portions of it to disk, or will you get out-of-memory exceptions?

10:56 clgv: SurlyFrog: no. If you hit the -Xmx limit the JVM will die with an exception

10:56 SurlyFrog: clgv: okay, thanks...

10:57 clgv: is -Xmx a command line option to the JVM?

10:57 clgv: yes

10:57 SurlyFrog: thanks

10:58 cemerick: well, the thread of execution that hits the allocation limit will throw that exception…which can be caught and recovered from. OutOfMemoryErrors don't actually terminate the JVM process.

10:58 clgv: hm right. never tried to catch one yet ;)

10:59 SurlyFrog: cemerick: okay.

11:00 cemerick: ,(try (byte-array Integer/MAX_VALUE) (catch OutOfMemoryError e "you're safe!"))

11:00 clojurebot: cemerick: Huh?

11:00 cemerick: wha?

11:00 &(try (byte-array Integer/MAX_VALUE) (catch OutOfMemoryError e "you're safe!"))

11:00 lazybot: java.lang.SecurityException: You tripped the alarm! catch is bad!

11:00 cemerick: oh hell

11:00 anyway, it works outside of a sandboxed environment

11:00 twhume: llasram: OK, thanks for your help. I now have a class being loaded OK; any idea how I would force it to be unloaded (so that I can load a new class in under the same name)?

11:05 llasram: twhume: My understanding is that you don't explicitly "unload" the class. You load it again w/ a different class loader, which gets a new Class instance representing the new class version

11:05 These classes are never resolved through normal JVM class resolution, but instead always go through Clojure namespace lookup mechanisms

11:06 twhume: OK, but the class loader in this case is a locally scoped variable inside the load-class function. If I were to pass a new instance of the class loader into that method each time, do you think that would do it?

11:06 (I'm guessing that the class loader won't be GCed until classes it's loaded are...)

11:15 clgv: twhume: a class has a reference to it's classloader

11:16 twhume: clgv: yup. So the loaded and the class have to go. I can sometimes force them out by doing ns-unmap followed by a GC, but it doesn't seem reliable. I think I'll do something else to work around this… it's quite important for my application.

11:17 clgv: twhume: what is your big picture?

11:17 twhume: As in, what's the app?

11:17 clgv: so to say

11:18 twhume: A bit wacky; I'm writing a "superoptimiser" for Java byte code - essentially, doing an exhaustive search for optimal programs across all possibilities. So I'm generating many classes, loading them, testing each one, testing if it works, and (usually) discarding it.

11:19 gfrederi`: is there a CLJS equivalent to (extend-type Object ...)?

11:19 (i.e., something that covers all the JS types)

11:20 clgv: twhume: oha, ok.

11:22 matthavener: twhume: have you seen the minikanren presentation on bliptv ?

11:22 dnolen: gfredericks: extend-type default

11:23 twhume: matthavener: nope

11:23 matthavener: those minikanren guys write a program that generates arbitrary programs that result in the number 6

11:23 might be interesting to you

11:23 twhume: This one? http://blip.tv/clojure/dan-friedman-and-william-byrd-minikanren-5936333

11:23 matthavener: yes, near the end

11:24 twhume: Thanks very much - I'll give it a look. There have been superoptimisers for specific hardware (SPARC, RS6000, 68000), but none for the JVM...

11:26 gfredericks: dnolen: cool thx

11:28 TimMc: dnolen: Did you see the core.match weirdness I posted?

11:28 I can't get a minimal test case since it's nondeterministic...

11:28 dnolen: TimMc: no, there's a lot of core.match weirdness, matching what kind of type?

11:29 TimMc: keywords

11:30 dnolen: TimMc: link or gist?

11:30 TimMc: dnolen: https://www.refheap.com/paste/2937 but it doesn't fail reliably (or in isolation?)

11:31 dnolen: TimMc: what is the weirdness the error?

11:32 Chiron_: hi! what is wrong with this http://pastie.org/4002330

11:32 CompilerException java.lang.RuntimeException: Unable to resolve symbol: server in this context

11:33 dnolen: TimMc: hmm, yeah not sure what's going on and don't have the bandwidth to pursue. Feel free to open a ticket with more details - patch even better of course.

11:35 clgv: Chiron_: the content of your doseq: (1) the ~ (2) there is one pair of parenthesis which is too much

11:35 jcromartie: hooray for -webkit-overflow-scrolling: touch;

11:37 TimMc: dnolen: OK, we'll probably just drop it for now. Macro-expansion of the match clause looks fine -- I can't see how it would fail. If we get anything reproducible I'll open a ticket.

11:37 ezyang: Hello folks. I was wondering if there were any implementations of STM-ized mutable data structures.

11:38 Or if this is even a good idea at all.

11:38 dnolen: TimMc: thanks much! Yeah I do not recommmend relying on core.match until it hits beta status.

11:38 ezyang: probably not a good idea I'd think.

11:39 ezyang: dnolen: How many references would the structure have to use before it became a bad idea?

11:42 Certainly, it wouldn't be "more than one", since the whole point about STM is to deal with multiple references properly.

11:43 S11001001: ezyang: when it comes to collections, there are only three numbers: 0, 1, and many.

11:43 dnolen: ezyang: do you just mean allowing mutable data structures to participate in STM? isn't that what a most STM research has been trying to do all along? (is not an STM expert)

11:43 S11001001: yes, and it's slow as hell

11:44 ezyang: so the correct answer is it's fine, as long as your data structure has either 0 or 1 element(s)

11:45 do more stuff immutably; STM gets a lot less interesting then

11:47 ezyang: S11001001: OK. The difference is something like 'one STM var per index on data store' to 'one STM var per element stored'

11:47 I wonder if there is a middle ground.

11:50 * dnolen is working CLJS source map support

12:04 goodieboy: I'm using an agent w/send-off for async http requests. Under what circumstances will my agent "fail", and how to do I completely avoid failure from happening? Use a top-level try/catch in my agent function?

12:06 nDuff: goodieboy: an unhandled exception, and yes... though "completely" is a little strong; there _are_ uncatchable exceptions in the JVM.

12:06 goodieboy: ...the proper Right Thing is to check for failure when you're going to interact with the agent, and deal with it then.

12:07 goodieboy: nDuff: ahh, right before I attempt to call send-off?

12:09 nDuff: That's what I generally do. That said, there _is_ a race condition there, so it's probably not the best pattern.

12:12 goodieboy: ...catching the exception from trying to do a send to a failed agent, and handling it there, would be the safer thing.

12:13 goodieboy: ...that said, if you aren't checking the value the agent holds anyhow, there's a decent chance that you're doing something for which a different concurrency mechanism would be more appropriate.

12:13 s/doing something/doing is something/

12:18 goodieboy: nDuff: yes, you're right. I don't care about the value of the agent. Should I be doing something else?

12:21 nDuff: goodieboy: ...to quote Joy of Clojure: "In cases where you just need a bunch of worker threads banging away on some work, or you have a specific long-running thread polling or blocking on events, or any other situation where it doesn't seem useful that the Agent maintain a value [...] there's every reasot to consider using a Java Thread directly, or a Java executor"

12:22 goodieboy: (if you have your own copy -- this discussion is in 11.3.5, pages 254-255)

12:23 goodieboy: nDuff: ahh ok, thanks

12:23 nDuff: ...except the book doesn't contain that typo :)

12:23 s/reasot/reason/

12:25 S11001001: is the pool used for sends accessible?

12:26 duck1123: if you're using the new version of lamina, it has some nice helper functions for managing tasks on thread pools

12:26 nDuff: S11001001: the executors are public static on clojure.lang.Agent, so it's _possible_ to access them

12:26 S11001001: whether it's _wise_...

12:29 technoma`: planning on cutting a lein release today

12:29 anything else that should be considered for it?

12:30 this one is going out mostly in order to fix a bug in the repl and add support for encrypted credentials

12:31 clgv: lein2 or lein1.7.x?

12:31 technoma`: 2.0.0-preview5

13:02 pbuckley: Anyone know how I can use C-x-e (emacs slime) in a function that relies on args or values from destructuring without having to temporarily def those args/bindings?

13:03 like how do I test the inner fn "some-fn" in (defn build? [some-arg] (some-fn some-arg)) without having to temporarily do (def some-arg "foo")?

13:04 by "test" I mean C-x-e

13:17 lpetit: hello

13:19 tmciver: pbuckley: I don't believe you can. C-x C-e just 'evaluates' code, it does not call the fn.

13:19 locojay: hi anything similar to python os.path.join (to make sure between unix and win paths...)

13:19 tmciver: pbuckley: To test your inner fn you'd just have to rely on test for the outer fn, or break out the inner fn.

13:19 joegallo: pbuckley: you could C-c C-e instead, and then type (build? "whatever-arg-you-want")

13:20 or (some-fn whatever-arg), for that matter

13:20 raek: locojay: yes. (clojure.java.io/file "foo" "bar" "baz")

13:20 locojay: thnks

13:20 raek: that produces a File object (which represents a path)

13:20 lpetit: Shameless plug: Counterclockwise (the Clojure Eclipse Plugin) now has decent leiningen 2 support in its (quite stable) beta version. With the ability to create new projects via a wizard wrapping lein new new (so you also get templates for free)

13:24 For those interested, more info here: https://groups.google.com/d/topic/clojuredev-users/UhfnjBvIips/discussion

13:25 Bronsa: cool lpetit

13:30 gfrederi`: why would naive-recursive-fib be 20 times slower in clojure than java?

13:31 amalloy: gfrederi`: best explanation: you're doing something wrong? i certainly can't guess without seeing any code

13:31 gfrederi`: amalloy: okay I'll pull it together

13:31 amalloy: eg, boxing is going to cost you a little, but not 20x

13:31 pbuckley: tmciver, joegallo, thanks, looks like I just have to break out the inner fn

13:33 gfrederi`: amalloy: refheap.com/paste/2944

13:34 amalloy: I guess the clojure could be changed to case?

13:35 amalloy: cemerick: OOM errors can trash your JVM pretty badly though, unless every thread knows how to deal with them at any time (pretty unlikely). thread 1 allocates almost-all the memory, then thread 2 gets an OOM and dies, then thread 1 gets an OOM, recovers, and throws out its excess crap

13:36 cemerick: amalloy: fair point

13:38 technoma`: is it or is it not idiotic that exceeding your thread limit throws an out of memory exception?

13:38 * technoma` is leaning towards the former

13:38 amalloy: technoma`: the JVM just can't remember all the dang threads you want

13:39 gfrederi`: and that's 20x faster in java? even on clojure 1.2 i wouldn't expect that big a difference

13:40 you could try hinting with ^int, on x and on the parameter vector (to hint the return type)

13:41 gfrederi`: amalloy: I'll verify the runtimes in just a sec

13:42 amalloy: running (time (fib 40)) in clojure prints ~7 seconds

13:42 amalloy: oh cool, case actually has code in it to special-case "all the test clauses are for ints, don't bother hashing anything"

13:43 gfrederi`: `time java ...` runs in 0.75 sec INCLUDING jvm startup time

13:43 amalloy: switching to case cuts it down to ~6.5 sec

13:43 jcromartie: gfrederi`: are you counting the Clojure startup time?

13:43 gfrederi`: jcromartie: nope, running the time macro from a repl

13:44 jcromartie: ah ok

13:44 amalloy: &(-> (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])) (nth 40)) ;; just checking the number

13:44 lazybot: ⇒ 102334155

13:44 kmicu: &(time (-> (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])) (nth 40)))

13:44 lazybot: java.lang.ClassNotFoundException: clojure.core

13:45 gfrederi`: kmicu: obviously that will be much faster

13:45 Raynes: Man, I sure wish I knew what caused that.

13:45 $login

13:46 lazybot: You've been logged in.

13:46 Raynes: $reload

13:46 lazybot: Reloaded successfully.

13:46 Raynes: $`foo

13:46 &`foo

13:46 lazybot: java.lang.ClassNotFoundException: clojure.core

13:46 amalloy: gfrederi`: adding ^long hints speeds it up 10x

13:48 bordatoue: hello

13:48 is it safe to use double as a key in hashmap

13:49 S11001001: bordatoue: what's safe?

13:49 kmicu: in cljs repl it takes 3ms in my clj repl 8 ms :)

13:49 S11001001: &({1.0 42} 1)

13:49 lazybot: ⇒ nil

13:51 gfrederi`: amalloy: oh we tried with Long; yeah primitives are much better

13:52 Bronsa: yes

13:52 gfrederi`: &(let [x 1.7e90] ({x 12} x))

13:52 lazybot: ⇒ 12

13:52 bordatoue: S11001001: safe in the sense, will there be key misses

13:52 when computing hash

13:52 gfrederi`: bordatoue: only if your doubles aren't quite equal

13:52 bordatoue: can you use ratios instead of doubles?

13:54 bordatoue: i can try

13:55 gfrederi`: ratios are much less scary

13:55 bordatoue: but is it recommended to use double as key in hashmap, what is the function used to create hashcode

13:55 gfrederi`: amalloy: with case and primitive typehints it is only 3 times slower

13:56 maybe for var lookup?

13:58 technoma`: bordatoue: if you're performing lookup on a map from Clojure functions the numbers will hash correctly. if you're using Java methods to get at them then the required broken Java semantics will apply.

13:58 bordatoue: technoma`: thanks,

13:58 technoma`: Could you please tell me how java would result in incorrect result when using double

13:59 technoma`: Basically i just want to know how different it will be

13:59 technoma`: I don't really know the details; I just know Java requires you to confirm to incorrect semantics if you claim to support certain interfaces.

13:59 bordatoue: technoma`: You could point me to some resource I can read , it would be great

13:59 technoma`: I think you can have both (Long. 1) and (Integer. 1) as separate keys or something?

14:00 no idea how doubles play into that

14:00 gfrederi`: oddly type-hinting the parameter vector slowed it down significantly

14:00 and eleminating the var lookup doesn't help either

14:01 amalloy: technomancy: that got fixed in 1.4 though

14:01 maps now use equiv instead of equals for key uniqueness

14:01 technoma`: amalloy: I thought the clojure functions were fixed in 1.3 but the java methods were still broken due to the requirements of the java interfaces?

14:02 amalloy: the clojure functions certainly weren't fixed in 1.3 - that was when the breakage became obvious, because longs became the default box

14:03 whether the java methods are broken, i don't know about

14:03 technoma`: oh, I'm talking about Integer/Long equivalence; primitives are another can of worms

14:04 bordatoue: Can anyone suggest a method to check if using double is safe as key in java hashmap

14:04 amalloy: as am i

14:05 i think

14:05 bordatoue: step 1 has got to be "decide what you mean by that question"

14:06 ,*clojure-version*

14:06 clojurebot: {:interim true, :major 1, :minor 4, :incremental 0, :qualifier "master"}

14:06 amalloy: &*clojure-version*

14:06 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

14:06 amalloy: i hate you both

14:06 hiredman: you want 1.5?

14:06 bordatoue: amalloy: when i say safe, it means something would work consistently

14:07 amalloy: hiredman: 1.3

14:07 hiredman: pffft

14:07 1.3 is bad and no one should use it

14:07 amalloy: i agree!

14:07 technomancy claimed something worked in 1.3, and i was hoping to prove him wrong

14:10 S11001001: bordatoue: it isn't nondeterministic, you will definitely either get a key match or a key mismatch for any two values

14:11 bordatoue: S11001001: could there be a key miss

14:12 S11001001: bordatoue: well you'd want key misses, wouldn't you, otherwise what's the point of a map?

14:13 ok, I'll put it this way

14:13 bordatoue: S11001001: due to floating point precision can there be key misses

14:14 S11001001: you can't deal with precision and have =

14:14 let me formalize

14:14 forall a b c in values where c is not nil. (= a b) implies ({a c} b) => c and (not= a b) implies ({a c} b) => nil.

14:17 bordatoue: S11001001: thanks

14:17 I will do some research on it

14:39 locojay: anyone using congomongo . when doing an update! call i keep on getting <#WriteResult N/A> on stdout. anyway i can prevent the output

14:43 amalloy: locojay: stop calling println on the result of the update? there's really no other reason it would print

14:44 gtrak`: hmm, is swank supposed to be able to M-. to a protocol def?

14:45 technoma`: I don't think so

14:58 emezeske: this is weird; someone is claiming authorship of lein-cljsbuild in the comments: http://technomancy.us/158

14:58 is that a spam-bot copying your content from another source?

14:59 emezeske: technoma`: that it is. I did write that comment, months ago, on some other blog

14:59 crazy!

15:00 technoma`: did you misspell "plugin" in your comment as well? =)

15:00 weird that there's no URL associated with the post

15:00 emezeske: I hope I didn't :(

15:00 TimMc: Nope.

15:01 kilon: that make no sense, what would be the benefit for a spam bot ?

15:01 TimMc: It is probably doing that as a probe. Some spambots will use unique strings so they can do a web search later to find out if their comment was approved.

15:01 locojay: amalloy: i don't have any print at all https://gist.github.com/2845411 line 5 does the output

15:01 technoma`: kilon: possibly testing the anti-spam defenses?

15:01 amalloy: emezeske: no hits for "leiningen plguin" anywhere on the web

15:01 technoma`: yeah

15:01 * emezeske does a fist pump.

15:01 technoma`: emezeske is cleared =)

15:01 kilon: ah i see

15:01 TimMc: The original: http://ubercode.de/blog/settling-down-with-clojurescript

15:01 The bot stripped out all tags, too.

15:01 technoma`: damn; better wipe that comment before the bot finds it

15:02 amalloy: locojay: (update! ...) returns a WriteResult, so if you're just printing the result of that (say, in the repl)...

15:02 technoma`: clever bugger; the content *almost* makes sense

15:02 locojay: runing via lein run and main

15:02 kilon: companies with too much free time in their hands

15:02 no wonder why global economy goes to hell

15:02 technoma`: in fact if it had been on my most recent post and I didn't already know emezeske then I wouldn't have suspected a thing

15:03 raek: I vagely recall that "lein run" prints the result of the -main function for some reason

15:03 emezeske: technoma`: That is a clever way to keep your comment from being deleted

15:03 technoma`: hm; that explains the nonsense alphanumerics in the URL field too

15:03 it's a token for checking up on later

15:03 TimMc: indeed

15:03 technoma`: Alter the token, cause havoc?

15:04 technoma`: TimMc: mwahaha

15:04 I've heard of people writing tarpits that have slowly-increasing latencies to gum up the bots

15:04 solussd_: I'm getting a compiler error "can't recur here" from clojurescript- I've narrowed it down to this: https://www.refheap.com/paste/4fc7bf16e4b09302d009a309 could anyone tell me why I can't recursively call that function?

15:05 hiredman: there is no recur in that function

15:06 solussd_: what makes you think it is that function?

15:06 (my guess it is your code calling that function)

15:06 solussd_: hiredman: b/c taking it out makes the compiler error go away. :)

15:06 in fact, removing the (map?) condition stops the error

15:06 emezeske: solussd_: are you up to date with your compiler version?

15:07 hiredman: doseq may be broken in clojure script

15:07 emezeske: solussd_: I know I've encountered that before, but I can't remember where :(

15:07 doseq works just fine

15:08 Oh, I think maybe cond is not supported in older clojurescript versions (?)

15:08 solussd_: emezeske: it compiles w/o the map? condition though

15:08 dnolen: emezeske: cond has been there since the beginning far as I know.

15:08 solussd_: it's definitely the recursive call that is making it blow up

15:08 emezeske: dnolen: Okay, color me crazy then

15:08 solussd_: i'm using the version of clojurescript pulled in by noir-cljs: [org.clojure/clojurescript "0.0-1236"]

15:09 amalloy: emezeske: early versions didn't have case

15:09 emezeske: amalloy: Thank you for preserving my sanity, "case" is definitely what I was thinking of

15:09 dnolen: solussd_: create a minimal reproducible case, open a ticket

15:10 solussd_: dnolen: k.

15:19 piranha: hi, if I have a question regarding clojurescript one and lein, should I ask it here, go to #clojurescript or to #leiningen? :)

15:20 kilon: you can ask it here too

15:21 piranha: sure. I'm trying to get cljs one up and running, but then (probably because I have lein2) none of the examples work

15:21 for example, they say run "lein repl" and then "(go)"

15:22 function go is not defined in my repl

15:22 dev-server is not defined as well

15:22 and I'm a bit lost already what to do :\

15:23 technoma`: have you tried lein-cljsbuild?

15:23 piranha: hm, nope

15:23 dnolen: piranha: CLJS one has seen much activity lately, it's pretty out of date as far CLJS far as I know.

15:23 amalloy: seancorfield: i'm digging through congomongo to remove the remaining reflection warnings. there are a number of cases like (.method ^GridFS f arg), where arg can be one of several types

15:23 dnolen: has not seen

15:23 amalloy: i have a macro in useful, multi-hinted-let, that can easily expand to something like (condp instance? arg File (.method ^GridFS f ^File arg), InputStream (.method ^GridFS f ^InputStream arg) ...). would you prefer that i (a) add a dependency on useful in project.clj, (b) copy/paste the macro into congomongo, or (c) just do it by hand every time?

15:24 dnolen: piranha: best to start with lein-cljsbuild at this point

15:24 technoma`: piranha: yeah, lein-cljsbuild seems a lot more usable

15:24 piranha: dnolen: ah, so it's better to skip it and just do...

15:24 ok, I see, thanks :)

15:33 antares_: seancorfield, amalloy: Monger uses helper protocols to coerce things like arg in this example (where possible)

15:34 other clojurewerkz.org projects do the same, it works pretty well (although there are cases where something like multi-hinted-let would still be necessary)

15:35 amalloy: antares_: so does congomongo in other cases, but for example GridFS/createFile accepts either a byte[] or a File or an InputStream, and there's no zero-overhead way to coerce those into a single thing

15:36 antares_: amalloy: yeah, I am not saying helper protocols are zero overhead. But it is OK for most needs (less overhead than reflective calls). Here's what monger uses, FYI: https://github.com/michaelklishin/monger/blob/master/src/monger/gridfs.clj

15:39 amalloy: antares_: the other thing i'm doing is removing all the unnecessary typehints from congomongo - looks like monger could use some of the same treatment :)

15:39 antares_: amalloy: yeah. Monger was my 2nd clojure library, it has a lot of things I'd like to clean up. Pull requests are welcome :)

15:46 clojure-newcomer: hi guys, I'm trying to do multi method dispatch on a key… I found a working example that dispatches on the value of a key ':name', but my data has arbitrary keys… http://pastebin.com/wpjaBKWU

15:46 I've made a failed attempt below the working example

15:49 dnolen: clojure-newcomer: make key return the relevant value for a particular map.

15:50 clojure-newcomer: if you're looking for the general case, not possible with multimethods - would require predicate dispatch.

15:50 clojure-newcomer: dnolen: I think you are saying I need to change my data structure because its not possible to do what I am trying to do ?

15:51 dnolen: clojure-newcomer: changing your data structure won't help you.

15:51 clojure-newcomer: it sounds like you want different methods to run if a key is present

15:52 clojure-newcomer: dnolen: yes I think so, so a certain function called if a key ':id' is found, different function for ':blurb' etc etc

15:52 dnolen: clojure-newcomer: not possible with multimethods

15:52 clojure-newcomer: dnolen: nuts, thanks for saving me time anyhow :-)

15:53 dnolen: I think I can flip it on its head and work with the value anyhow, thx for the help

15:53 ezyang: Can someone help me out: I can't find where Clojure's jvm code keeps track of nested transactions.

15:54 runInTransaction seems to always attempt to commit the transaction at the end.

15:54 What am I missing?

15:55 TimMc: Are you sure they nest?

15:55 Maybe dosync always joins any open transaction.

15:55 ezyang: there are claims on the Internet that they do. But I might be wrong :-)

15:55 hiredman: they nest

15:56 ezyang: have a look at clojure.core/sync

15:57 ezyang: That just calls LockingTransaction.runInTransaction

15:57 I'm staring at that code right now.

15:57 hiredman: right, which looks for a locking transaction where?

15:58 ezyang: So, it checks if there is a current transaction. But then regardless of whether or not there was a running transaction, it invokes t.run(fn)

15:58 I think that's wrong. I also think that this will have the wrong semantics if a retry is necessary.

15:59 hiredman: why do you think it is wrong?

15:59 a transaction joins the current transaction if there is one already running

16:00 ezyang: Yes, that is correct.

16:00 The problem is what happens when the inner transaction finishes.

16:00 hiredman: what about it?

16:00 ezyang: If you straightline the code, you get something like:

16:01 transaction.set(t = new LockingTransaction()); ... /* no set */; fn.call; t.run(fn2); .... t.run(fn1)

16:02 hiredman: that is not correct

16:02 ezyang: Unless I'm super misunderstanding what t.run does, I think it finalizes the transaction

16:02 I think that's what the code is doing.

16:02 hiredman: do you have code that demos the problem?

16:02 ezyang: No. It'd probably be a very fiddly race to cause too.

16:03 oh, actually, no, this should be pretty simple.

16:03 just a sec.

16:03 hiredman: you cannot "straighline" the code, it is nested

16:03 ezyang: hiredman: What I mean by "straightline" is saying what a hypothetical execution would step through.

16:04 hiredman: that is incorrect in that sense too

16:04 ezyang: OK, help me understand why this doesn't happen.

16:04 hiredman: fn1 would start executing before fn2 and finish executing after fn2 finishes

16:04 (where fn2 is a nested transaction)

16:04 ezyang: No, that's not right.

16:04 hiredman: it is right

16:05 ezyang: fn.call is responsible for calling the function.

16:05 hiredman: fn2 code is run from inside fn1

16:05 ezyang: Yes, I inlined that in my example.

16:06 hiredman: (sync nil (X (sync nil Y))) turns in to (.../runTransaction (fn [] (X (../runTransaction (fn [] Y)))))

16:06 ezyang: Yes.

16:07 hiredman: so the outermost fn is fn1, and the inner most is fn2

16:07 ezyang: So when you enter the inner runTransaction, you run fun2's code, and then run t.run(fun2)

16:07 hiredman: right

16:07 which happens while fn1 is running

16:07 ezyang: I think running t.run(fun2) finishes up the transaction.

16:07 and then when fn1 finishes running, it runs t.run(fun1)

16:08 devijvers: greetings, can anybody tell me how attribute selectors work in enlive?

16:08 hiredman: ezyang: no

16:08 they are nested, t.run(fn2) cannot happen unless t.run(fn1) is running

16:09 ezyang: OK, let me state my assumptions.

16:09 1) fn.call() in runInTransaction is responsible for running the code inside fn

16:10 2) If fn contains a runInTransaction, when fn is finished running, all of the lines in runInTransaction will have run.

16:11 3) In our example, we first runInTransaction on fn1. fn.call() causes fn1 to be executed, and doesn't return until fn1 is done executing.

16:12 hiredman: it depends for some cases the fn.call line is never reached

16:12 in the facse of the outmost transaction the fn is run inside the call to t.run(fn) not fn.call()

16:12 because info will be null

16:12 ezyang: OK, that is true.

16:13 3') In our example, we first runInTransaction on fn1. t.run(fn1) causes fn1 to be executed, and that f.call() doesn't return until fn1 is done executing.

16:13 combining (3') and (2), because fn1 contains a runInTransaction, when /that/ f.call() line returns, all the lines in runInTransaction on fn2 have finished executing.

16:14 hiredman: correct

16:14 ezyang: OK.

16:14 hiredman: so what happens for fn2 is it goes right to t.run(fn2)

16:14 ezyang: 4) A line of that runInTransaction is t.run(fn2)

16:14 aha! return is short circuiting.

16:14 Ok, we're good.

16:14 hiredman: *eyeroll*

16:15 ezyang: Sorry, this is why I came and asked :-)

16:18 devijvers: hey, can anybody help me with attribute selectors in enlive?

16:18 amalloy: ~anyone

16:18 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

16:19 devijvers: I want to write this selector: select[name=somename]

16:20 ystael: What is the most idiomatic way to filter a seq by a predicate which may have side effects so is required to be evaluated exactly once for each seq element? (I don't care _when_ the predicate is evaluated, only that it is at most once each)

16:20 s/at most/exactly/

16:21 bobry: emezeske: is it possible to pass --define to closure compiler?

16:21 emezeske: bobry: Nope.

16:21 bobry: ouch <_<

16:21 why?

16:21 clojurebot: bobry: because you can't handle the truth!

16:22 bobry: turns out the only way to override 'goog.LOCALE' is pass --define goog.LOCALE=...

16:22 emezeske: bobry: Well, for one, it's not called from the command line, so passing command line arguments doesn't really make sense

16:22 TimMc: Sure it does.

16:23 emezeske: bobry: And nobody's created a nice way to set all of the google closure options in the clojurescript compiler

16:23 mstump: I'm getting an exception which doesn't make sense. I'm passing a string to a Java constructor, and I keep getting "java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.Comparable" which doesn't make sense because String implements Comparable. Any ideas?

16:23 TimMc: mstump: Look at the [L

16:23 kmicu: bobry: you have fix for that http://dev.clojure.org/jira/browse/CLJS-77

16:23 TimMc: That means you have an array of something.

16:23 emezeske: bobry: I'd love to have all of the google closure options exposed, they're just not. There's about a billion of them.

16:23 hiredman: mstump: you are not calling the constructor you think are calling

16:23 TimMc: mstump: I'll hazard a guess that you're running into varargs.

16:24 mstump: That constructor does take a vargs Comparable

16:24 what should I be doing?

16:24 bobry: I see.. and thanks kmicu ;)

16:24 TimMc: Passing in an array.

16:24 Varargs is a lie.

16:25 &(class (into-array ["foo"])) might do it

16:25 lazybot: ⇒ [Ljava.lang.String;

16:26 devijvers: how do I write this selector in enlive? select[name=somename]?

16:27 locojay: if i do map #(some funciton) on a lazy seq nothing happens do i have to use a doall ?

16:28 emezeske: bobry: This is where the google closure options get set. Very basic at the moment. 'Twould be awesome for this to be configurable, maybe via a callback that sets the options: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L76

16:28 devijvers: locojay: yes

16:29 locojay: if you use map as a replacement of a loop you're better off with for

16:30 dnolen: emezeske: bobry: patches welcome

16:30 mstump: That was it. Thank you! That was a horrible fcking exception. I want my morning back. Someone should be violently penetrated with a cactus.

16:31 locojay: devijvers : thanks. i was planning to use pmap and and upload function to my db to upload in parrallel so i m not sure if for is better

16:32 bobry: dnolen: great! btw, is there a reason, cljs doesn't accept pull requests?

16:32 dnolen: bobry: because that's not approved Clojure process.

16:33 emezeske: dnolen: I wish I had more time to allocate to the cljs compiler... Maybe someday soon. :)

16:33 bobry: oh, where can I read more about the process?

16:33 dnolen: bobry: on the Confluence pages.

16:33 bobry: emezeske: I like the callback idea, can you submit a patch? :)

16:34 emezeske: bobry: Unfortunately, my time to interest ratio in that particular feature is rather low :(

16:34 kmicu: dnolen: i can write a patch, but my idiomatic clojure sucks for now :] and jonase/kibit it's not so good to fix that :P and seriously what is wrong with this http://dev.clojure.org/jira/browse/CLJS-77

16:34 bobry: except for patch formatting :)

16:36 devijvers: locojay: can't think of a better solution than pmap

16:36 how do I write this selector in enlive? select[name=somename]?

16:37 bobry: kmicu: I think this needs a more generic solution, the patch in CLJS-77 only covers --define

16:37 locojay: devijvers: not at the moment as i m a total novice

16:37 dnolen: bobry: kmicu: patch looks ok and applies - just confirmation from someone that it works for them.

16:39 bobry: would welcome a more generic patch.

16:41 bobry: dnolen: sure, should I create a separate issue?

16:44 dnolen: bobry: feel free, have you sent in your CA?

16:44 TimMc: devijvers: Doesn't the Enlive wiki have an example of that?

16:46 devijvers: TimMc: thx!! found it on the wiki: these selectors requre double brackets, now it works

16:47 bobry: dnolen: nope, not yet, can you merge the patch from CLJS-77, while the CA flies all the way from Russia? :)

16:48 dnolen: bobry: if you can confirm that it actually works

16:48 bobry: okay, let me check then

16:53 devth: anyone know if clojure.contrib.cond ever got a replacement? looking for a cond-let

16:58 if there's not a replacement for an old contrib, what's the correct way of making one?

17:00 kmicu: devth: http://dev.clojure.org/display/design/Moving+Projects+Into+Contrib

17:01 devth: kmicu: thanks, but doesn't that only apply to 1.2 and below?

17:02 also, i'm not the original author. i just want an old contrib to use in my project.

17:03 S11001001: (<<- (if-let [x whatever] x) (if-let [y whatever] y) otherwise)

17:03 trivial expansion target, combined with flipped ->>

17:06 coventry`: What's the status of clojure in clojure? Is there a public repository for it?

17:06 dnolen: coventry`: ClojureScript is effectively C-in-C

17:07 technomancy: coventry`: there hasn't been much movement on replacing the Java in Clojure with Clojure

17:08 coventry`: I read that the project was blocking on an inefficiency in Clojure's object creation (http://blog.n01se.net/blog-n01se-net-p-41.html) Is that still the case?

17:09 dnolen: coventry`: that is very old, the mechanisms for building on host types are already in place.

17:11 coventry`: Thanks. So the recent work on speeding up operations on native ClojureScript object operations (the benchmark graphs which were posted here recently), is that at the clojure-in-clojure level, or is that hand-tuned js?

17:12 dnolen: conventry`: barring some 7 lines of interop, nothing in ClojureScript written in JS.

17:13 conventry`: the compiler is tuned to emit optimal JS

17:13 hiredman: dnolen: once the clojure datastructures are replaced with onces written in clojure ported from clojurescript implementations then I will buy that

17:13 coventry`: Thanks for the info.

17:13 clojurebot: We live to serve.

17:14 coventry`: You too, clojurebot. :-)

17:14 dnolen: hiredman: if you want to wait for that, *shrug*

17:15 hiredman: dnolen: until then clojurescript is just "clojurescript in clojure"

17:15 clojurescript isn't selfhosting

17:15 neither is clojure

17:18 dnolen: hiredman: more *shrug* :)

17:20 technomancy: I'll believe it when I see (ns clojure.var)

17:20 hiredman: dnolen: so why keep saying "clojurescript is effectively clojure-in-clojure"?

17:20 clojurescript is not clojure so it cannot be substituted as either instance of clojure in that expression

17:21 SurlyFrog: Can someone double check me. If a function is reading an atom, and during the course of the function, it is swapped out by another thread that changes the atom, the first function does not re-read the atom. Correct?

17:21 hiredman: and even if it could, you can't do it for both because clojurescript is written in clojure

17:21 dnolen: hiredman: because most of the language constructs are written in itself? is Clojure all the lame limitations imposed by the JVM? I think not.

17:21 brehaut: SurlyFrog: yes

17:21 hiredman: technomancy: (ns clojure.lang) (deftype Var [...])

17:22 SurlyFrog: brehaut: thanks :-)

17:22 S11001001: SurlyFrog: read via deref, right

17:22 dnolen: hiredman: and of course vice versa (limitations) for CLJS

17:22 technomancy: hiredman: yeah yeah--backwards compatibility; who needs it =)

17:22 hiredman: dnolen: clojure is specificly targeted at the jvm, clojurescript is specificly target at js

17:22 they are not the same thing

17:23 http://clojure.org/jvm_hosted

17:23 dnolen: hiredman: is Clojure a language or an implementation?

17:23 hiredman: *sigh*

17:24 dnolen: hiredman: do any of the things in Compiler.java that's not portable make any difference to the language?

17:24 hiredman: do you really want be to start quoting rhickey on the subject to you?

17:24 he went through this entire thing with clojure on the clr

17:24 dnolen: hiredman: uh, what quote?

17:25 hiredman: dnolen: lemme grep then

17:25 pipeline: clojure on the clr could be a cool thing but it wouldn't be clojure anymore

17:25 dnolen: pipeline: ClojureCLR exists

17:26 clojure-newcomer: hey guys… I'm using clj-time to try to get a DB field like '1065691975' converted into a decent format… trouble is I am getting 'No instant converter found for type: java.lang.Integer'

17:26 can I convert this Integer to a Long in clojure ?

17:27 I had thought to use 'from-long'

17:27 brehaut: ,(class (long (Integer. 1)))

17:27 clojurebot: java.lang.Long

17:27 miceiken: First time with clojure here, how can I comment a larger segment of code

17:27 brehaut: but i dont think thast actually answering the question

17:27 miceiken: instead of ;; each line

17:28 clojure-newcomer: brehaut: thanks!

17:28 TimMc: miceiken: There's no true multiline comment.

17:28 miceiken: However, #_ will make the reader ignore the next (valid!) form, and (comment ...) is a macro that will replace multiple valid forms with nil.

17:28 rhickey: http://vote.jax-awards.com/

17:29 TimMc: lol @ Jenkins

17:30 kmicu: where is thinkrelevance? :)

17:31 TimMc: This Restructure thing is such a Java-ish thing.

17:31 sjl: Is it possible to use swank-clojure (the lein plugin thing) with Clojure 1.4? Even if I require clojure 1.4 in my project's project.clj 'lein swank' always seems to produce a 1.3 repl

17:31 S11001001: ,(+ #_#_3 7 11)

17:31 clojurebot: 11

17:32 vijaykiran: sjl: which version of lein are you using ?

17:32 sjl: vijaykiran: 2.0.0-preview4

17:33 kmicu: hiredman: :dnolen 10:43-12.xx http://blip.tv/clojure/rich-hickey-unveils-clojurescript-5399498, so David was right

17:33 vijaykiran: sjl: lein repl is also giving 1.3 ?

17:33 sjl: vijaykiran: yeah

17:34 vijaykiran: sjl: I just created a sample project with 1.4/lein2-prev-3

17:35 sjl: seems to work fine *clojure-version* is 1.4

17:35 hiredman: kmicu: uh, "the compiler itself is written in clojure"

17:35 sjl: what/where is *clojure-version* defined?

17:35 vijaykiran: sjl: may be the deps you have in the project bringing different clojure version ?

17:35 bobry: dnolen: nope, the patch doesn't work

17:35 vijaykiran: sjl: type it directly into repl

17:36 jhulten: My googlefoo is failiing. How do I call a clojure function dynamically? for instance (let [name "action"] (execute (str "do-" name) arg) => (do-action arg)

17:36 dnolen: bobry: thanks for verifying.

17:37 hiredman: kmicu: "when you write macros for clojurescript, you write them in clojure" etc etc etc

17:37 bobry: kmicu: are you the author of the patch for CLJS-77?

17:37 sjl: oh cute, clojure.math.combinatorics and clojure.math.numeric-tower both required 1.3.0, so it silently ignored my 1.4.0 requirement in project.clj

17:37 technomancy: ugh; version ranges

17:38 any project that uses version ranges needs to have hell of bugs filed against it

17:38 vijaykiran: sjl: ^^ :)

17:38 amalloy: alternatively, a plague of locusts

17:38 sjl: I still want a language that enforces semantic versioning at the language level somehow

17:39 amalloy: sjl: that's probably harder than the halting problem, just fyi

17:39 technomancy: you could always take the go approach: never introduce a backwards-incompatible change ever

17:39 sjl: yeah, the "don't break your users' code" approach is a fairly solid one

17:39 technomancy: also more difficult than the halting problem though

17:40 hiredman: *shrug* you mean the people who get to use your code for free?

17:40 you should go out of your way to keep their code running?

17:40 sjl: hiredman: yes, because they're humans and wasting their lives is a dick move

17:40 `rand`-AFK: jhulten: use (symbol)

17:41 sjl: at least put a "don't use this project if you care about your sanity" warning label if you're going to break things a lot -- that's totally fine

17:41 hiredman: sjl: wasting yours working around their faulty assumptions is better?

17:41 emezeske: sjl: Nobody is forcing users to upgrade to a newer version of the language

17:41 sjl: emezeske: yeah I'm sure all the new libraries will continue to release security fixes compatible with old versions forever

17:41 hiredman: yes, it's called being a nice person

17:41 emezeske: sjl: They can always keep using the old version. If they want all the cool features or security fixes from a new version, they can choose whether it's worth making things work against breaking changes

17:41 nDuff: sjl: eh? The clojure version you require in your project.clj should override what your dependencies specify

17:42 sjl: nDuff: that's what I thought, but it doesn't

17:42 kmicu: bobry: nope, I only have used some solution based on that diff in ClojureScript One

17:42 sjl: emezeske: alternatively, library authors can grow up and care about backwards compatibility and everyone wins

17:42 amalloy: nDuff: not if version ranges are involved. thus, the locusts/bugs

17:42 nDuff: sjl: I'm really _very_ sure that, under normal circumstances, it does. I have dependencies which specify 1.2.0, and I very certainly get 1.4.0

17:42 emezeske: sjl: Are you the author of an open source library?

17:43 nDuff: sjl: ...it'd be interesting to look at the project.clj or pom.xml files for the relevant bits of tooling.

17:43 sjl: emezeske: yeah, a whole bunch, which I use Semantic versioning for

17:43 amalloy: if your dependency specified [1.2.0] instead of 1.2.0, then you would not get 1.4.0 no matter what your project.clj says, nDuff

17:43 emezeske: sjl: Then you know how much work it is. I also try hard for backwards compat.

17:43 sjl: But sometimes that weight can build up and drag you down

17:43 sjl: emezeske: it's really not that much work to write a few wrapper functions to preserve backwards compatibility

17:43 nDuff: amalloy: *nod*, which is why I noted that it'd be interesting to actually look at the relevant files.

17:43 emezeske: sjl: I beg to differ.

17:44 hiredman: backwards compatibility is just another trade off

17:44 emezeske: hiredman: Exactly

17:44 hiredman: Time spent on backwards compat is not spent on cool new stuff

17:44 nDuff: sjl: It depends. As I understand it, rhickey tries hard to stay backwards compatible, but only with behaviors he explicitly documented; anything which happens to fall out of the current implementation but isn't documented is liable to change at any time w/o notice.

17:44 emezeske: hiredman: Both are desirable, and it's a balancing act like everything else.

17:44 * nDuff considers this reasonable.

17:45 hiredman: the dick move is pretending you haven't made a trade off

17:45 sjl: nDuff: 1.4 doesn't seem to bad, 1.3 was a mess

17:45 technomancy: someone should write a lein plugin that tells you which of your dependencies have version ranges and opens your browser to the bug report page for those libraries

17:45 nDuff: technomancy++

17:45 hiredman: technomancy: people should use their version ranged deps via polycosm!

17:45 sjl: technomancy: if library specifies a range, will lein deps :tree show you the range or just a single number?

17:45 Chousuke: in Clojure's case, I think all backwards-incompatible changes have been good so far.

17:46 technomancy: sjl: just the number; it's collapsed down

17:46 sjl: technomancy: ah okay

17:46 technomancy: you could determine it's a conflicting range by looking at top-level :deps in project.clj and comparing though

17:46 * nDuff grumbles -- he's had a post sitting in the moderation queue for clojure-tools for well over a week now.

17:46 nDuff: (don't even remember what it was about anymore)

17:46 sjl: technomancy: numeric-tower and combinatorics don't seem to use project.clj -- they have pom.xml files

17:47 so I don't know where the range would be specified

17:47 technomancy: that's contrib for you =(

17:47 amalloy: Chousuke: 1.3 contained a big batch of bad incompatible changes. 1.4 reverted or otherwise addressed most of them

17:47 technomancy: it should be under <dependencies> -> <version>

17:47 hiredman: nDuff: http://www.leancrew.com/all-this/2012/04/where-modules-go-to-die/

17:47 sjl: technomancy: https://github.com/clojure/math.numeric-tower/blob/master/pom.xml

17:48 technomancy: hiredman: I just read the ruby equivalent to that post this morning

17:48 hiredman: it is a universal

17:48 brehaut: sneaking the name munging change into 1.2.1 was a pain

17:48 technomancy: sjl: bleh; maven is being object-oriented here and inheriting from another pom =\

17:49 sjl: but yeah, working on projects like Mercurial (which is wire-compatible to versions something like ~5 years old) made me realize that A) Backwards compatibility matters. and B) It's not that hard once you actually commit to it.

17:49 hiredman: project object model oriented programming

17:49 sjl: technomancy: ah

17:49 S11001001: wire protocols aren't apis

17:49 sjl: technomancy: so how can I use both numeric-tower and clojure 1.4?

17:49 glitch99: anybody know a trick for a memset of clojure - like 10 copies of the same element in a list?

17:49 sjl: S11001001: It's Mercurial's API, along with the CLI

17:49 hiredman: ,(doc repeat)

17:49 technomancy: sjl: you could add an :exclusions entry to your numeric-tower dependency

17:50 clojurebot: "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."

17:50 glitch99: hiredman: sweet! thanks!

17:50 sjl: technomancy: hmm, never seen that -- are there docs on it somewhere?

17:50 S11001001: implication doesn't imply equivalence

17:50 glitch99: clojurebot: also thanks!

17:50 clojurebot: I'm no man, and she's no lady!

17:50 technomancy: sure; `lein help sample` | grep :exclusions

17:50 sjl: S11001001: okay, replace "API" with "the part of your thing that real humans other than you are going to use"

17:51 technomancy: hm; well the grep doesn't really work since it cuts off a wrapped line but you get the idea

17:51 S11001001: right, even more of those things are different

17:51 technomancy: sjl: anyway, there's a time to commit to stability and a time to be experimental and explorative.

17:51 amalloy: technomancy: grep -C?

17:51 technomancy: amalloy: yeah, that

17:52 if I had to commit to stability on something like slamhound it would never get written

17:52 sjl: technomancy: right, and the time is either "version 1.0" or "lots of real people use this now and will have to waste time if you break it"

17:52 technomancy: you did the right thing with lein 2.0 -- I just wish more people did the same.

17:52 technomancy: the problem isn't that people break things, it's that they don't communicate expectations well

17:53 sjl: sure, putting "Don't use this if you care about your time" is fair warning. You're right -- people don't do that either.

17:53 hiredman: the problem is people use a software package and expect the next version to work the same way

17:54 which is why tools like maven are good, because you can lock a specific version and just use it

17:54 sjl: Yes. Why would a version that had *more* work put into it now be broken? Isn't it supposed to be *better* after more work?

17:54 hiredman: and not worry about "oh, I depended on this bug that got fixed, in what was a patch version, so I thought it was ok to upgrade"

17:55 technomancy: sjl: it's silly to think "better" is one-dimensional

17:55 sjl: technomancy: Partially, but it's important to remember that the only person who actually cares how pretty the internals are is you (plus other implementers)

17:56 People using the library care way more about "it's not broken" than "it's elegant inside".

17:56 technomancy: code that's easier to reason about has fewer bugs

17:56 sjl: Sure, except it's broken and now I need to fix things before I move on.

17:57 technomancy: it's complicated

17:57 sometimes it's worth it in an immature codebase

17:57 sjl: It's really not that hard to either 1) Provide little wrappers to stay backwards compatible or 2) Increment the major version and make it obvious that people are going to need to sit down and figure out how to deal.

17:58 hiredman: even in a mature codebase

17:58 sjl: yes!

17:58 hiredman: "this is slow and in efficient, it will now be fast, any stick in the mud who hates change is welcome to continue to use the old version"

17:59 etc

17:59 sjl: Sure, if you don't care about the time and frustration of other human beings that's a valid approach.

17:59 technomancy: often you're not free to use old code though; upgrades are contagious

17:59 antoineB: hello, can i talk clojure-script in this channel?

18:00 Raynes: We'd prefer English, but sure.

18:00 ;)

18:00 sjl: technomancy: exactly -- "use the old version" tends to be a valid option for a couple of months or so

18:00 technomancy: unless you use that fancy new polycosmosish thing I hear is pretty hot these days =)

18:00 borkdude: Esperanto is also accepted

18:00 hiredman: it is pretty sweet

18:00 :)

18:01 borkdude: or maybe emacs people like Ido more (http://en.wikipedia.org/wiki/Ido)

18:01 hiredman: it lets you be more free wheeling with your versions, you can stick with an old version and still move to newer versions of it's dependencies for your own code

18:02 technomancy: hiredman: curious why you didn't just use plain old classloaders thouh

18:02 though

18:02 do jboss models get you basically the same thing?

18:02 sjl: technomancy: okay this is weird

18:03 technomancy: http://paste.stevelosh.com/4fc7e98b58d2e20007000000?clojure

18:03 hiredman: technomancy: they get you more than classloaders, e.g. if you have two things that depend on clojure-1.2 they can share a clojure 1.2 runtime

18:03 sjl: technomancy: that results in http://paste.stevelosh.com/4fc7e99c58d2e20007000001 -- no clojure 1.3.0, which looks right

18:03 technomancy: hiredman: can't you do that by nesting your classloaders the right way though?

18:03 hiredman: I guess you aren't responsible for the tricky calculations on how to do that?

18:03 hiredman: technomancy: right

18:03 sjl: technomancy: but if I remove the exclusion from metrics-clojure, clojure 1.3.0 reappears under combinatorics in lein deps :tree

18:03 technomancy: hiredman: cool

18:03 sjl: how could that be?

18:04 hiredman: the plan for jboss modules seems to be that they will be compatible with whatever comes out of project jigsaw too

18:04 nDuff: technomancy: ...at least with the OSGi classloader-based model, I have trouble with thread-locals being left around by "unloaded" Clojure plugins, linked to their classloaders, which can't be unloaded in turn until everything they instantiated is gone. Not saying that there aren't approaches to track down and fix leftover thread-locals -- I think Tomcat makes the attempt on app unload -- but it's not always easy.

18:05 hiredman: nDuff: yeah that kind of thing is still an issue

18:05 polycosm doesn't attempt to provide a way to unload modules

18:05 technomancy: sjl: I think when multiple dependencies bring in a given dep there's not really one right answer for questions like that.

18:06 sjl: technomancy: okay, I lied -- it's just metrics-clojure bringing in clojure 1.3. But why does :tree put it under combinatorics?

18:06 hiredman: if X brings in A and B, and A and B depend on C, should A and B be visble to each other?

18:07 sjl: technomancy: and should I not be specifying a version of clojure in the metrics-clojure library anyway? Just tell people which one they need?

18:07 hiredman: it short of depends on what you mean by visible, and given clojure's implementation it is actually pretty tricky to avoid

18:07 technomancy: sjl: as long as you don't specify a range you're fine

18:07 hiredman: but dealing with that kind of stuff is what a module system does

18:08 sjl: seems strange that specifying a range (more flexibility) actually makes things less flexible...

18:09 technomancy: sjl: yeah, I didn't realize how horrible the implementation was for a long time and unfortunately encouraged their use for a wihle

18:09 while

18:09 amalloy: you can specify open-ended ranges like [1.3.0,], or some syntax like that

18:10 technomancy: amalloy: which is horrible for different reasons =)

18:10 amalloy: when i did that, people made fun of me "lol how can you know it will work with 1.6.3?"

18:10 TimMc: [1.3.0,1.3.9999999] is safer

18:10 technomancy: you can say it'll work with 1.3.0 up to but not including 2.0.0

18:10 amalloy: technomancy: sure you can

18:10 TimMc: it still doesn't protect you from alpha releases

18:10 technomancy: to which aether will be like "what's that? you want 2.0.0-SNAPSHOT? OK, here ya go!"

18:10 ಠ_ಠ

18:11 amalloy: and then if it happens to work with 2.0.0 anyway, people will still be annoyed

18:11 technomancy: amalloy: yeah, exactly why I don't recommend the 9999999999 approach

18:11 semantic versioning doesn't mean major version bumps must be completely incompatible

18:12 sjl: "Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API."

18:13 TimMc: technomancy: Unless you version your variable names too. :-P

18:13 amalloy: sjl: uhhhh, are you trying to disagree with technomancy? because he just stated that the converse is untrue

18:13 antoineB: i am trying to use the browser repl with a server (file:///myfile.....) and it doesn't works

18:14 sjl: amalloy: the other part is that there's no other place in that spec that says anything about incrementing major version numbers

18:14 TimMc: amalloy: Not even that.

18:14 "Completely" is the operative (and fun) word.

18:14 sjl: Well sure, they could happen to have only broken parts of the code you never use, that's true.

18:15 * TimMc forks and adds "MAY be incremented for marketing reasons"

18:15 amalloy: sjl: so what? "x MUST be done if y" does not mean "x MUST NOT be done if not-y"

18:15 sjl: But in the semver.org description of it, the ONLY time the major version is incremented is when you break something

18:15 pjstadig: if P, then Q does not imply if Q, then P

18:15 sjl: amalloy: yeah, but that's the only rule applying to major versions in the spec

18:15 amalloy: sjl: uh huh

18:16 pjstadig: in fact it is fallacious to draw that conclusion

18:16 amalloy: which is my point

18:16 and pjstadig's

18:16 technomancy: the more careful you are about bumping on every incompatible change the more likely it is that a bump will result from a change that doesn't affect some people

18:16 TimMc: sjl: It's not part of the spec, even though it might be a good idea.

18:16 sjl: Sure, you could also say "well he doesn't say NOT to increment the major version number when you eat Indian food for lunch that day!"

18:16 pjstadig: sjl: sounds good to me

18:16 amalloy: *shrug* and if i chose to increment the major version number once a year on my birthday, i would not be in violation of the spec

18:17 as long as i also bumped it whenever i broke something

18:17 sjl: amalloy: you are technically correct

18:17 the best kind

18:17 pjstadig: if the sun comes up, then the rooster crows, therefore if the rooster crows, then the sun will come up

18:17 but of course roosters don't make the sun come up

18:17 amalloy: sjl: the only kind. if the spec doesn't forbid something, then doing it can't cause you to be non-compliant. that's what a spec MEANS

18:18 sjl: amalloy: I guess I'm assuming some level of common sense here,

18:18 TimMc: pjstadig: Well, we've never tested that by taping all the roosters' beaks shut...

18:18 amalloy: TimMc, chicken-harasser incognito

18:19 arohner: is there a way to examine an agent's queue?

18:19 TimMc: sjl: I get annoyed at "needless" major version bumps, but I'd not say they're counter-spec.

18:19 arohner: and has anyone else ever wanted an agent's queue to be a sorted set? i.e. ignore duplicate calls?

18:19 TimMc: sjl: It certainly violates the Principle of Least Astonishment.

18:19 hiredman: arohner: perhaps you should put a set in your agent

18:20 pjstadig: TimMc: you do something major, so you bump the major version...doesn't astonish me

18:20 arohner: hiredman: I'm kind of hacking it. I don't really care about the value of the agent, I just want to serialize some I/O

18:20 pjstadig: "something major" is not necessarily equal to "something breaking"

18:20 sjl: TimMc: They might not violate the spec in the pedantic nerd version of it, but they do in the normal-human, spirit-of-the-thing version.

18:20 hiredman: arohner: :(

18:20 sjl: pjstadig: in semantic versioning yes, it is

18:20 TimMc: pjstadig: If it only adds stuff, it's a minor version bump.

18:21 hiredman: arohner: then just put a sorted set in a ref

18:21 sjl: pjstadig: http://semver.org/ is the spec we're talking about

18:21 TimMc: semver doesn't track cool, it tracks compatibility.

18:21 hiredman: run a loop in a future to read it and the io

18:21 technomancy: uh oh; pjstadig is violating semver

18:21 ~guards

18:21 clojurebot: SEIZE HIM!

18:21 arohner: hiredman: yeah, but I want the fn to be called when I call it, but if another call to f is already in the queue, throw it on the floor

18:22 sjl: The benefit to using it is that I can say "Foo works with version 1.4 or higher, but not anything starting with a 2 because that broke something"

18:22 That way I don't need to manually inspect each new version of the library unless the major version changed

18:22 hiredman: arohner: well that isn't an agent anyway, right? agents are asynchronous

18:22 borkdude: so emacs 24 is not compatible with 23?

18:22 sjl: borkdude: if they used semver, that would be the case, but I don't think they do

18:23 arohner: hiredman: I want async and serialized, I just want the queue to be a sorted set

18:23 amalloy: arohner: so put a ref around a set. or a queue, and have your alter function check to see if it should actually add anything

18:23 hiredman: arohner: right, but you don't want a reference, you don't care about the value

18:23 technomancy: borkdude: the answer, as always, is "it's complicated" =)

18:23 some things are compatible and some aren't.

18:23 hiredman: so you don't want an agent

18:23 sjl: borkdude: and anyway isn't the "24" in "emacs 24" short for "emacs 1.24" and it's just that no one ever writes the "1." any more?

18:23 I thought I read that somewhere

18:23 Could be wrong though -- I use Vim.

18:23 hiredman: so, stick a sorted set in a ref, have a thread read from the ref in a loop

18:23 done

18:24 borkdude: slj with java that is the case, with emacs I doubt it, but could be

18:24 technomancy: borkdude: no, he's right

18:24 TimMc: It doesn't always make sense to follow semver.

18:24 borkdude: technomancy ah, ok

18:24 TimMc: Apps like Firefox and Emacs... nothing really links against the UI.

18:24 Now, their internal components, sure.

18:24 sjl: Yeah, standalone GUI apps don't really make sense, definitely.

18:25 clojure-newcomer: hey guys, I've got dates stored as '1065706498' (int(11) in MySQL), I'm trying to get them out with clojure.java.jdbc and they are all coming up as 1970 or thereabouts….. how do I extract them correctly ? oh, I'm using clj-time

18:25 sjl: CLI ones do though -- the CLI becomes the public-facing API as soon as someone writes a bash script.

18:25 borkdude: technomancy where can I find that?

18:26 pjstadig: meh

18:27 that's enough bikeshedding for me for today

18:27 technomancy: borkdude: wikipedia says "Versions 2 to 12 never existed. Earlier versions of GNU Emacs had been numbered "1.x.x", but sometime after version 1.12 the decision was made to drop the "1", as it was thought the major number would never change."

18:27 so I guess that's a little different from 24 technically still being 1.24

18:27 pjstadig: hehe

18:28 jjido: clojure-newcomer: maybe times 1000? This timestamp is in 2003 using Unix epoch

18:28 pjstadig: "these are not the major numbers you are looking for"

18:28 pipeline: emacs also stopped development for a really, really long time

18:29 all "interesting" things happened inside of xemacs or another fork first for a really l ong time

18:29 emacs 22 came out in '07 and development has been really rapid since then

18:29 clojure-newcomer: jjido: could you tell me a little more about this, sorry

18:29 TimMc: Java will never go 2.0. Python is pretty much stuck at 2.x.

18:29 hiredman: java went 2.0

18:29 and is now at 7

18:29 technomancy: pipeline: I think it still came in under the XP->vista gap though =)

18:30 S11001001: TimMc: I'm a 3k believer :)

18:30 pjstadig: clojure-newcomer: that doesn't seem like a clojure issue. ask the person who created the database and inserted the data what the numbers mean

18:30 TimMc: hiredman: Eh, Java 7 is the marketing name, but it is Java v1.7.

18:30 gfrederi`: you'd think there weren't any major numbers above 5

18:30 hiredman: TimMc: 1.7 is the jvm version

18:30 S11001001: wasn't it java 2 v1.2, java 2 v1.3?

18:30 pipeline: technomancy: yes, technically, but versions 18 through 21, particularly 18, 19, 20, were so similar that you might as well compare them to service packs

18:30 pjstadig: clojure-newcomer: java dates can be constructed with number of millis since epoch, you may need to do some work to convert the fields to millis

18:31 gfrederi`: versions could be like points in pinball -- you add 500 at the slightest provocation

18:31 TimMc: hiredman: Mmm, interesting... I'll have to think about that.

18:31 gfrederi`: Well, Firefox already went full retard with versions.

18:31 clojure-newcomer: thanks guys

18:31 pjstadig: clojure-newcomer: i think what jjido suspects is that they are actually the number of seconds since epoch, which means you'd have to multiply my 1000

18:31 clojure-newcomer: I'll have a look

18:31 pjstadig: *by

18:31 jjido: clojure-newcomer: it is a JDBC issue, find how it interprets timestamp from your db.

18:31 gfrederi`: TimMc: the only thing retarded is all opinions except my own

18:31 ethanis: hey guys, I'm trying to setup testing in a clojure project and use leiningen to run the tests

18:32 pjstadig: but he said they are int(11) fields, not date fields

18:32 so my guess is JDBC brings them out as integers

18:32 ethanis: but whenever I call "lein test", the output is: "Exception in thread "main" java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate sherbondy/test/point_api__init.class or sherbondy/test/point_api.clj on classpath"

18:32 hiredman: jjido: most likely since he says "I am using clj-time" he is turning the ints in to dates badly

18:32 clojure-newcomer: pjstadig: yes int(11)

18:32 ethanis: is there some sort of classpath voodoo I need to do to set things up properly?

18:32 TimMc: ethanis: Did you name the file with an underscore or a hyphen?

18:32 ethanis: hyphen

18:33 clojure-newcomer: hiredman: same problem if I construct from java.util.Date with Long in constructor

18:33 TimMc: ethanis: There's your problem.

18:33 ethanis: woohoo

18:34 technomancy: welcome to the JVM where the filenames are made up and the points don't matter

18:35 brehaut: lol

18:35 i liked the original british JVM better than the US remake

18:36 hiredman: the british jvm is for toffs

18:36 technomancy: but there was that one episode where Stephen Fry made a cameo

18:37 as the G1 garbage collector

18:37 wait, are toffs good or bad?

18:38 brehaut: clearly they are good

18:38 otherwise hiredman wouldnt be making any sense

18:39 * pjstadig googles toffs

18:39 pjstadig: http://en.wikipedia.org/wiki/Toff

18:39 derogatory

18:39 and mildly so

18:42 zomg: Hi, I wonder if there are any common gotchas or such in Clojure for people not familiar with it?

18:42 technomancy: zomg: contains?, isa?, and partition don't do what you think they do.

18:42 zomg: I'm converting some Java code into Clojure, and while I've managed to make the code compile, it doesn't work the same way as the Java code does

18:42 So just wondering if there's anything that could easily trick you before I go through the code again for the 5th time to find out if I did some stupid mistake somewhere

18:42 =)

18:42 technomancy: also don't use protocols, defrecord, or deftype until you have a few months of experience

18:43 zomg: Yeah I don't even know what those are... =)

18:43 technomancy: even better! =)

18:43 don't mix laziness and side effects

18:43 we need like a ten commandments for newbies

18:43 hiredman: zomg: that is generally a bad idea, clojure code for the same task is often very different from the java code

18:44 zomg: hiredman: Yeah I'm not doing one to one code of course :)

18:44 gfrederi`: technomancy: that was impressive

18:44 zomg: but more like rewriting it to do the same job

18:44 technomancy: gfrederi`: I, uh... spend a lot of time on IRC.

18:44 gfrederi`: ~gotcha

18:44 clojurebot: Cool story bro.

18:44 zomg: I've done some Haskell before so I'm not *completely* lost ;)

18:44 But only passingly familiar with any lisp like languages

18:44 gfrederi`: clojurebot: gotcha is contains?, isa?, and partition don't do what you think they do.

18:44 clojurebot: Roger.

18:44 gfrederi`: ~gotcha

18:44 clojurebot: gotcha is contains

18:44 technomancy: don't write any macros in your first three months

18:44 gfrederi`: crap

18:45 technomancy: please make your language sound as much like new-parent advice as possible

18:45 technomancy: haha

18:45 borkdude: also, only use def/defn on top level expressions

18:45 zomg: "do not drop the baby"

18:45 pjstadig: don't expect any sleep for at least 2 months

18:46 arohner: hiredman: FYI, you can get at the agent's queue with wallhack field, but the items in the queue aren't amenable to being put in a set, because each fn gets a new (binding-conveyor-fn) wrapped, which kills equality

18:46 zomg: Oh regarding defn, is there a difference between using 'do' in it or not? :P As in, (defn foo [] (one) (two)) vs (defn foo [] (do (one) (two)))

18:46 gfrederi`: zomg: no diff

18:46 zomg: I noticed the docs for certain things like when and when-not say they have an implicit do, but I wasn't really able to find out anything concrete

18:46 technomancy: zomg: sounds like you're asking the right questions at least. =)

18:46 pjstadig: uh oh

18:47 let's not open up that can of worms

18:47 gfrederi`: pjstadig: there's a diff?

18:47 pjstadig: when vs. if can be very contentious

18:47 gfrederi`: oh nm

18:47 well there is technically one difference

18:48 pjstadig: zomg: i think the answer is that defns have an implicit do as well, so the do is unnecessary

18:48 zomg: Ah I see

18:48 gfrederi`: (fn [] {:pre [false]} :x) is definitely not the same as (fn [] (do {:pre [false]} :x))

18:48 but you wouldn't do that anyways

18:48 hiredman: arohner: also it is just a bad idea, as everyone (all 2 of us) that have responded to you have said

18:49 the semantics you want are not the semantics of agents, so stop trying to use them

18:49 zomg: Well, thanks for the pointers. I guess I'm going over my code once more to find that mistake I did =)

19:03 ethanis: hmm, how can I preserve my shell's environment variables when using lein repl/test?

19:04 as in, I have defs which rely on System/getenv calls

19:04 or is there a better way of going about this? profiles?

19:04 technomancy: the environment should be preserved

19:04 (just ask Captain Planet)

19:04 sorry

19:04 ethanis: haha

19:06 even the temporary environment created by a call of source?

19:06 here's my setup:

19:06 I have a local .env file containing various API keys

19:07 to test, I figured I could call source .env

19:07 technomancy: ethanis: try export $(cat .env)

19:07 ethanis: alright!

19:07 technomancy: ethanis: curious, is this for heroku?

19:07 ethanis: yep

19:08 technomancy: cool; have fun =)

19:09 ethanis: great, it works! thanks technomancy.

19:48 devn: i wonder... does it make sense to port pprint to clojurescript?

19:51 klauern: howdy

19:52 antoineB: i just start to do a simple "hello world" in clojure-script

19:53 it give me 19000 lines

19:53 brehaut: have you used advanced compilation?

19:53 antoineB: no

19:53 amalloy: good thing the computer writes them for you, eh?

19:53 brehaut: that would be why then

19:56 devn: antoineB: {:optimizations :advanced, :pretty-print :false}

20:00 antoineB: 5400 lines, it is probably more than my application will need

20:01 devn: antoineB: perhaps

20:02 antoineB: not everyone needs jquery or clojurescript

20:03 antoineB: i try to build a schema maker with the svg element

20:06 in 708 lines i do "simple direct link", "box wiith text", "context menu", "serialization/deSerialzation"

20:11 devn: antoineB: why do you think it is 700 lines?

20:12 antoineB: until no it is 700lines

20:12 devn: sorry. why do you think it is 5400 lines?

20:12 antoineB: i just count them

20:13 devn: antoineB: yes. but why do you think it is 5400 lines?

20:13 TimMc: I wonder what jquery weighs in at these days.

20:13 antoineB: i make a simple hello world compile then with advance but with pretty print and give me a js file

20:14 brehaut: 9404 lines

20:14 TimMc: ^

20:14 devn: antoineB: i understand. think about why the output is that big. do you know why?

20:14 antoineB: realy?

20:15 devn: unfortly not

20:15 devn: antoineB: http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html

20:15 TimMc: brehaut: Huh. That's the uncompressed, right?

20:15 brehaut: TimMc: yes

20:15 antoineB: if you wrote hello.c compiled it and statically linked it with libc would you be surprised if it was large?

20:16 TimMc: compressed im pretty sure its only one line

20:18 TimMc: heh

20:18 devn: haha i was thinking the same thing

20:22 fil512: how do i add something to the front of a vector?

20:22 antoineB: devn: i think the code is the goog stuff

20:23 technomancy: fil512: depends, do you care the tiniest bit about performance?

20:23 fil512: not so much...

20:23 antoineB: brehaut: no, but the libc embrace also the browser stuff

20:23 brehaut: err

20:24 devn: fil512: why do you want to add to the front of a vector? what do you want to accomplish?

20:24 fil512: the reason I want to stick it at the start is to make it easy to use update-in, e.g. (update-in :foo 0 :bar 0

20:24 technomancy: fil512: ok, in that case you can do something goofy like (vec (cons x myvec))

20:24 hiredman: into!

20:24 technomancy: oh yeah

20:25 fil512: I'd love it if I could go (update-in :foo $ :bar $) or sth to mean "last"

20:25 technomancy: ,(into [:head] [:middle :tail])

20:25 clojurebot: [:head :middle :tail]

20:25 fil512: nice!

20:25 TimMc: Huh, cute.

20:25 fil512: thanks!

20:26 TimMc: Hmm. update-in would make a nice protocol.

20:27 devn: cute indeed

20:27 TimMc: Each layer could decide how much of the key list to consume.

20:28 For instance, a 3rd-order tensor would consume 3 integer keys.

20:33 brehaut: ,(for [:let [a [1 2]] b a] (inc b))

20:33 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Can't pop empty vector>

20:33 brehaut: ,*clojure-version*

20:33 clojurebot: {:interim true, :major 1, :minor 4, :incremental 0, :qualifier "master"}

20:35 antoineB: good night

20:37 TimMc: brehaut: Same in 1.3.0. What's up?

20:38 brehaut: just curious

20:39 its also the same in 1.2; i just wondered if it had been fixed on a new version

20:39 hiredman: what for really needs is :do

20:39 TimMc: brehaut: Fixed, as in... better error message?

20:40 brehaut: well, let you have a :let at the start of a for

20:40 technomancy: hiredman: :let [_ (horrible-side-effects)]

20:40 oops, beat me to it

20:41 hiredman: well, duh

20:41 I would just prefer :do to having to do that

20:41 saml: hey, how can I watch a directory tree for modification?

20:41 something like inotify on linux

20:41 technomancy: saml: you need java 7 to do it portably IIRC

20:41 TimMc: That's a common question these days.

20:42 saml: cool i just downloaded jdk

20:42 7

20:42 technomancy: hiredman: that comes dangerously close to endorsing side effects in laziness

20:42 ugly things should be ugly

20:43 * technomancy &

20:43 lazybot: java.lang.RuntimeException: EOF while reading

20:46 hiredman: technomancy: sometimes you gotta log

20:46 :do in doseq would be nice too

20:52 TimMc: Explain to me again the use-case for a :let at the beginning of a for form?

20:53 hiredman: you have a for inside a let, and you want to pull it up a level

21:13 _KY_: I did a "lein clean" before "lein uberjar" but I still get "java.language.NoClassDefFoundError", how to fix that?

21:20 hiredman: I don't see how people expect to get anything done when they go around throwing out all the information that comes with an exception

21:20 _KY_: This is the error log:

21:20 https://www.refheap.com/paste/2950

21:22 hiredman: what does the ns form for genifer.core look like?

21:25 _KY_: 1 sec...

21:25 (Ands genifer.core

21:25 (:require [genifer.forward_chaining :as forward])

21:25 (:require [genifer.backward_chaining :as backward])

21:25 (:require [genifer.core :as core])

21:25 (:require [clojure.main])

21:25 (:require [clojure.string :as string :only [split triml]])

21:25 (:gen-class)

21:26 brehaut: _KY_: http://refheap.com etc

21:26 _KY_: First line should be (ns

21:26 hiredman: those underscores should be hyphens

21:26 you only need a single :require

21:26 xeqi: why does genifer.core :require itself?

21:26 _KY_: But it used to work...

21:27 hiredman: that's not right either

21:27 _KY_: no it didn't

21:27 _KY_: The file name is with the underscore

21:27 hiredman: sure

21:27 the file name has an underscore

21:27 the namespace name should have a hyphen

21:28 _KY_: you tricked yourself in to thinking it worked somehow

21:28 but it did not

21:28 _KY_: Namespace is just genifer.core

21:29 The file is exactly "forward_chaining.clj"

21:29 hiredman: sure

21:29 _KY_: You mean I change it to hyphen in the file name?

21:29 hiredman: no

21:29 the file name stays the same

21:29 _KY_: Alright

21:29 hiredman: but the namespace for the namespace backed by that file should have a hyphen

21:30 clojure trys to make things simpler by giving the .clj file name the same file name as the generated class, and java doesn't allow '-' in classnames

21:31 but in clojure the convention is to use '-' in symbols to separate words

21:31 namespaces are named by a symbol

21:31 so the namespace genifer.forward-chaining lives in the file genifer/forward_chaining.clj

21:32 and this is why most people just avoid hyphens or dashes when it comes to namespaces

21:33 joegallo: here's something totally bizarre

21:33 hiredman: _KY_: so there are a number of problems with that ns form, the one that is stopping your code from loading is most likely the namespace requiring itself

21:33 joegallo: oops, wrong channel -- you tricked me hiredman!

21:33 hiredman: hah, now people in #clojure know you can talk

21:34 _KY_: Do you mean clojure automatically changes my namespace to forward-chaining?

21:35 But I declared the namespace in that file to be genifer.forward_chaining

21:35 hiredman: don't do that

21:35 it should be genifer.forward-chaining

21:35 brehaut: underscores in clojure space names is non-idiomatic style, even when it works

21:36 not to mention plain ugly

21:37 _KY_: So I keep the file names, and change the space names?

21:37 Is that allowed?

21:37 ethanis: hey guys, has there been any talk of tweaking the load-lib function in clojure.core so that the :only option accepts an individual symbol in addition to a seq of symbols?

21:37 _KY_: I thought it's required that file name = namespace name

21:38 ethanis: I'm new to clojure, and I keep getting tripped up and accidentally typing (:use some-package :only bla) when I only want to use one function

21:38 I guess this would make the use function inconsistent

21:39 but it seems like a pragmatic tweak

21:39 thoughts?

21:39 hiredman: ethanis: use :require not :use

21:39 _KY_: I have been using :only blah without [] and it seems to work

21:39 ethanis: ah, so it's just poor form to do :use if I only want a single function?

21:42 tmciver: ethanis: not because you only want one function; use is discouraged - use require.

21:42 ethanis: _KY_: what version of clojure are you using? (use '[clojure.string :only lower-case]) definitely does not work for me.

21:42 ah, use is just generally discouraged because require is more explicit?

21:43 _KY_: 1.3.0

21:43 gtrak: I find 'use' obfuscating

21:43 ethanis: sure, I understand why

21:43 _KY_: I use :require in ns

21:44 brehaut: use is also unnecessary with :refer in 1.4+'s require

21:44 though still useful at a repl

21:44 hiredman: _KY_: have you read the docstring on require?

21:44 (you may find that there is no :only option, so clojure is silently ignoring you)

21:46 _KY_: Oh really

21:46 saml: hey, if anyone is using La Clojure, how would I import lein project to that IDE?

21:46 gtrak: where's an example of the :refer feature?

21:48 ethanis: don't actually do this

21:48 brehaut: ,(do (require '[clojure.set :as set :refer [difference]]) (difference (set/union #{:a} #{:b}) #{:b}))

21:48 clojurebot: #{:a}

21:48 ethanis: but an example

21:48 oh, never mind

21:48 brehaut: gtrak: ^

21:49 gtrak: ah, neat

21:49 ethanis: even so

21:50 gtrak: ,(difference #{:a} #{:a :b})

21:50 clojurebot: #{}

21:50 ethanis: it'd be nice to be able to type (require '[clojure.set :as set :refer difference])

21:50 but you could make the case

21:50 hiredman: denied

21:50 brehaut: clojure.set/difference cares about ordering

21:50 ethanis: that it'd just be more typing later the moment you decide to refer another function

21:50 gtrak: ,(difference #{:a :b} #{:a})

21:50 clojurebot: #{:b}

21:51 brehaut: gtrak: theres a math word for that and i cant remember waht it is

21:51 transitive?

21:51 associative?

21:51 one of those

21:51 gtrak: associative

21:51 brehaut: thanks

21:52 aperiodic: well, if it cares about ordering, then it's *not* associative

21:52 gtrak: right

21:52 * aperiodic takes off pedant hat

21:53 metellus: I think you mean commutative

21:53 brehaut: this is why im no good at math

21:53 ethanis: alright folks, thanks for the style tips re: use of require

21:54 night

21:54 aperiodic: "ordering" in the (a (b c)) vs ((a b) c) sense

21:54 not the (a b) vs (b a) sense

21:54 gfrederi`: What's purple and commutes?

21:54 aperiodic: an abelian grape!

21:54 gfrederi`: AAAAHAHAHAHAHHAA

21:54 * aperiodic high five

21:55 gfrederi`: o/

21:55 aperiodic: \o

21:55 gfrederi`: my work here is done

21:55 _KY_: ,(docs ns)

21:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: docs in this context, compiling:(NO_SOURCE_PATH:0)>

21:55 aperiodic: i'm partial to the "what's purple and takes the train to work?" version, myself

21:55 _KY_: ,(doc ns)

21:55 clojurebot: "([name docstring? attr-map? references*]); Sets *ns* to the namespace named by name (unevaluated), creating it if needed. references can be zero or more of: (:refer-clojure ...) (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class) with the syntax of refer-clojure/require/use/import/load/gen-class respectively, except the arguments are unevaluated and need not be quoted. (:gen-class .....

22:05 _KY_: I don't know why but I changed my deps and now lein won't work

22:05 It's always noClassFound for this and that file

22:06 The namespace, require etc used to work

22:15 TimMc: Hey, Light Table hit 300 kilobucks!

22:26 abp: TimMc: Thanks, reminded me that i meant to pledge too..

22:26 TimMc: :-D

22:27 xhh: abp: you got 19 hours left ;)

22:29 abp: xhh: I know, but then I surely would miss the deadline. Where waiting the last months, despite knowing i will pledge eventually .

22:43 _KY_: Oh I found out... I was opening 2 sessions of lein at the same time =)

22:43 Almost drove me nuts

23:03 irc2samus: hi guys, if I were to capture SIGINT in order to do cleanup I should use the Java way that is registering a shutdown hook like it's said here: http://stackoverflow.com/questions/2541475/capture-sigint-in-java right? or is there a Clojure-specific way that is preferable?

23:03 technomancy: irc2samus: shutdown hook is best

23:04 irc2samus: great thanks!

23:40 zomg: Neat, managed to whip together a desktop streaming application even though I had never used clojure before :D

23:40 Using xuggler with ogg theora encoder and html5 video as the "target" where you can view the desktop stream

23:41 on my local box only about 1-2 seconds of latency so not bad I think =)

23:41 prob worse over a network tho

23:42 irc2samus: so guys, do I need gen-class for the shutdown hook thread? or is there a more "direct" way to define the function to run there

23:45 Lajla: Chousuke, mun rakkaus, oletko täällä?

23:48 irc2samus: hmm there's a "proxy" thingy that seems to do it

23:51 abp: irc2samus: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/ have a look at that chart and deceide

23:55 technomancy: irc2samus: you don't need anything fancy to create a thread, just pass it a function

23:55 (.start (Thread. #(do :some 'stuff)))

23:56 well, don't start it in this case I guess

23:58 irc2samus: lots of options :) the proxy thing worked, copied it from here: http://java.dzone.com/articles/clojuretest-introduction

Logging service provided by n01se.net