#clojure log - Sep 05 2010

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

3:53 LauJensen: Good morning all

3:53 Raynes: Morning.

4:12 LauJensen: bozhidar: What we were seeing last night, was probably a bug in Awesomes event reporting, as soon as I moved the program to Windows everything worked and the layout resized as expected

4:13 bozhidar: LauJensen: I wouldn't have thought of that

4:13 but it's nice to hear you figured it out

4:13 LauJensen: 'awesome' is a hack :|

4:13 bozhidar: awesome - the tiling WM I presume?

4:14 LauJensen: Yea

4:14 At least I assume its responsible for sending the event

4:14 bozhidar: I don't think so

4:15 I think that X handles this directly

4:15 but awesome might be consuming something that it shouldn't

4:16 but then again - this is just a guess, I am far from an X event handling expert :-)

4:17 LauJensen: I think if you read about the design goals of X, it wouldn't be a stretch to imagine that it outsources event handling

4:17 hiredman: I have heard of tiling window managers and swing not interacting well

4:18 LauJensen: This might be one such case

4:35 tnoborio: Hello all.

4:36 (File. _nil_ "fname") raise no exception, but why (File. nil "fname") raise exception "More than one matching method found"?

4:36 (def _nil_ nil)

4:36 I wonder this behavior.

4:37 LauJensen: ,(java.io.File. _nil_ "fname")

4:37 clojurebot: java.lang.Exception: Unable to resolve symbol: _nil_ in this context

4:37 tnoborio: ,(def _nil_ nil)

4:37 clojurebot: DENIED

4:39 tnoborio: Why not the same behavior?

4:39 (File. nil "file path"), (File. _nil_ "file path")

4:40 _nil_ is defined nil, or return of function.

4:41 LauJensen: Good question

4:53 Ive had this problem a couple of times now. I have a namespace, which when evalled in the REPL works as expected, but when compiled it throws an Illegal state exception saying spit is already defined in another namespace, which it isnt

4:53 Anybody tried that?

5:03 tnoborio: That's right, I tried code,

5:05 LauJensen: fixed, I had put a :use where a :require belonged :)

5:05 hiredman: Have you got an idea about tnoborios problem above?

5:06 tnoborio: I put gisthub. http://gist.github.com/565876

5:19 I think Its related java.io.File have 2 constructor, File(String parent, String child) and File(File parent, String child), and parent allow null.

5:35 _ulises-: morning

6:18 fullets: b

6:35 bartj: converting this java code - IOUtils.copy(inputStream, writer);

6:35 to Clojure I do: (IOUtils/copy input-stream writer)

6:36 But, I am almost certain that there is no way I can get the contents of the writer back

6:36 because copy returns a void

6:36 fullets: (let [writer (new StringWriter)] (IOUtils/copy input-stream writer) (str writer)) ?

6:38 bartj: fullets, let me try that...

6:40 fullets, that works, thanks!

6:41 though, I thought that would not be possible, because Clojure is immutable

6:42 fullets: Clojure's variables/data-types are immutable, but Clojure doesn't make mutable Java types immutable.

6:43 ,(doto (new java.util.ArrayList) (.add "foo") (.add "bar"))

6:43 clojurebot: #<ArrayList [foo, bar]>

6:48 bartj: fullets, yeah thanks!

6:48 fullets, writing/converting Java code to Clojure is so un-intuitive (functionally)

6:50 Chousuke: you pretty much need to rethink the whole thing :P

6:51 you can translate java into clojure if you're in a hurry but the result won't be spectacularly beautiful :)

6:53 bartj: Chousuke, it is outright ugly :)

6:56 I also reckon I am doing something wrong, which makes it look ugly

6:58 raek: bartj: you might want to check out clojure.java.io: http://clojure.github.com/clojure/clojure.java.io-api.html

6:58 it has a copy function

6:58 Chousuke: bartj: well if you're just writing "java in clojure" it won't look good no matter what you do :P

6:59 bartj: for eg, I will give an example below which I think is ugly and there must be a better way to do it:

6:59 statusCode = obj1.method1().method2().method3() -> this is in Java

6:59 and to convert it to Clojure, I do something like:

6:59 obj2 (.method1 obj1)

6:59 statusCode (.method2 obj2)

7:00 is there any better way to do the above

7:00 mrBliss: (.. obj1 method1 method2 method3)

7:00 Chousuke: I prefer (-> obj .method1 .method2 .method3)

7:00 bartj: Chousuke, that seems great!

7:01 mrBliss, thanks

7:01 Chousuke: (fewer parens than the java line :P)

7:01 bartj: haha

7:02 Chousuke: if the methods take args you can do (-> obj (.method args) .method2 ...)

7:02 raek: also, don't mix InputStreams/OutputStreams (which are byte-oriented) with Readers/Writers (which are character-oriented)

7:02 Chousuke: and you can also use clojure functions or macros in ->.

7:03 which is why I prefer it over ..

7:04 bartj: -> and ->> are the only macros that I know good enough to use frequently (apart from #_)

7:04 sexpbot: java.lang.Exception: Can't take value of a macro: #'clojure.core/and

7:04 Chousuke: bartj: I'm sure you're using defn, and, or and when pretty often too :)

7:05 bartj: ok maybe amongst the exotic(!) ones

7:05 Chousuke: fn is actually a macro too but that's a secret :P

7:10 bartj: I also have some "doto" in the code

7:10 is that preferable over "->" or "->>"

7:11 mrBliss: they're not interchangeable

7:12 ->(>) applies the next function to the result of the previous and doto applies every function to the first argument

7:12 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (0) passed to: core$-GT-

7:13 Raynes: Be careful with those exceptions. They're collectible.

7:15 bartj: mrBliss, yes, thanks, I guess I was a bit over-zealous

7:51 Licenser: ->(doc some)

7:51 sexpbot: => ------------------------- clojure.core/some ([pred coll]) Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example thi... http://gist.github.com/565974

7:52 Vinzent: Hello all. I need an advice about macros. How can I access parameters of function that defined in macros?

7:54 e.g. I have something like (defmacro defaction [name params] `(defn ~name ~params)) and need generate code to process or examine fn parameters

8:11 ssideris: Licenser: hello... I've tried running your swing example with the temperature conversions

8:12 and it seems that you have changed the clj-swing api a bit since you wrote this, right?

8:14 (i'm referring to the example at your blog)

8:14 great work with clj-swing by the wa

8:14 y

8:16 I'd be interested to contribute some code for tables, but I'm still working on learning clojure

9:31 LauJensen: clojurebot: contribute is http://clojure.org/contributing

9:31 clojurebot: Ik begrijp

9:31 LauJensen: clojurebot: contribute is http://clojure.org/contributing

9:31 clojurebot: Ack. Ack.

9:31 LauJensen: clojurebot: contribute is http://clojure.org/contributing

9:31 clojurebot: 'Sea, mhuise.

9:31 LauJensen: clojurebot: contribute is http://clojure.org/contributing

9:31 clojurebot: In Ordnung

9:31 LauJensen: ssideris: see the link above

9:37 ssideris: thanks

10:34 Bahman: Hi all!

10:35 LauJensen: Bada... ehm, .. Hi Bahman :)

10:37 Bahman: LauJensen: Hey there :-)

11:36 _na_ka_na_: hello, are :user/a & ::user/a the same ?

11:37 chouser: not always

11:38 ,::user/a

11:38 _na_ka_na_: but if i define a key :user/a .. it gets looked up by ::user/a also

11:38 clojurebot: :user/a

11:39 _na_ka_na_: ,{:a 10 :user/a 20 ::user/a 39}

11:39 clojurebot: Duplicate key: :user/a

11:39 chouser: ,(alias 'ccore 'clojure.core)

11:39 clojurebot: nil

11:39 chouser: ,::ccore/a

11:39 clojurebot: :clojure.core/a

11:39 chouser: ,:ccore/a

11:39 clojurebot: :ccore/a

11:39 _na_ka_na_: ooh hmm subtle difference ..

11:40 chouser: the double-colon tells the reader to use namespace aliases to resolve the prefix part of the keyword

11:40 with a single colon, the prefix part is taken literally, without resolution.

11:41 kumarshantanu: if I execute (while true) on clojurebot, will it hang?

11:41 chouser: since 'user is the real name of a namespace, it resolves to itself and thus ::user/a and :user/a mean the same

11:41 kumarshantanu: afraid of running it in real

11:41 chouser: kumarshantanu: it should time out after a few seconds.

11:42 _na_ka_na_: ,{:a 10 :ccore/a 20 ::ccore/a 39}

11:42 clojurebot: {:a 10, :ccore/a 20, :clojure.core/a 39}

11:42 _na_ka_na_: cool thanks chouser

11:44 chouser: np

12:04 tnoborio: The question before, Does anyone have a idea? why raise exception http://gist.github.com/565876

12:05 LauJensen: chouser: I'd love to hear your oppinion on tnoborio's problem

12:06 chouser: tnoborio: the first two File lines would fail at runtime

12:07 the third one fails at compile time because the compiler can be certain of the type of the first arg -- specifically, that it's nil

12:10 tnoborio: the first two File lines success, (File. _nil_ "fname") ; => #<File fname>

12:10 chouser: hmph.

12:10 ok, hang on a sec.

12:10 tnoborio: (File. (identity nil) "fname") ; => #<File fname>

12:13 chouser: my repl's broken at the moment. let me fix it and then I'll try to figure out what's going on

12:16 interesting. So File has two different ctors that take two args.

12:16 the difference is the type of the first arg: String or File

12:17 when you pass in nil, which should Clojure use?

12:17 LauJensen: ,(str nil)

12:17 tnoborio: I think the compiler need certain of the type, the first File line should be raise error.

12:17 clojurebot: ""

12:18 chouser: when you pass a literal nil (File. nil "fname"), the compiler (rightly, I think) complains that it doesn't know which to call.

12:18 when you pass something that will return nil at runtime, the compiler at compile time just emits some runtime reflection code.

12:19 then when that reflection code runs at runtime, it apparently chooses one of those two ctors without complaint -- but I still don't know which its calling or how it chooses.

12:19 tnoborio: I think you may be right, that it ought to complain at runtime in that case.

12:22 tnoborio: Thanks, understand.

12:23 Chousuke: I suppose you can't type-hint nil either? :P

12:24 notsonerdysunny: can I define my own equality function which would be used for comparison in a multi-method?

12:25 Chousuke: the dispatch function can be anything

12:26 notsonerdysunny: ,(defn mclass [s] |nil

12:26 clojurebot: notsonerdysunny: Gabh mo leithscéal?

12:26 notsonerdysunny: (reverse (loop [ret '() val s] |user> (mclass

12:26 (if (coll? val) | "132213123")

12:26 (recur (cons (class val) ret) (first val)) |(java.lang.String)

12:26 (cons (class val) ret)))))

12:26 sorry ..

12:27 ,(defn mclass [s] (reverse (loop [ret '() val s] (if (coll? val) (recur (cons (class val) ret) (first val)) (cons (class val) ret)))))

12:27 clojurebot: notsonerdysunny: Huh?

12:28 tnoborio: Or the compiler accept (File. nil "fname") and it matche File(String, String) like (File. (identity nil) "fname").

12:31 notsonerdysunny: chosuke .. oh right ..

12:31 Chousuke: hm

12:32 notsonerdysunny: ,((defn mclass [s] (reverse (loop [ret '() val s] (if (coll? val) (recur (cons (class val) ret) (first val)) (cons (class val) ret))))) #{'([{1 2}])})

12:32 clojurebot: notsonerdysunny: Titim gan éirí ort.

12:32 chouser: hm. so at runtime, the reflection code runs the first method that matches.

12:32 Chousuke: notsonerdysunny: instead of using reverse and consing onto a list, you should use a vector as an accumulator instead.

12:32 chouser: it doesn't appear to make any attempt to discover if there's more than one that would work.

12:33 Chousuke: or (map (fn [x] (class (if (coll? x) (first x) x))) somecoll) :P

12:39 notsonerdysunny: Chousuke: my function would return (clojure.lang.PersistentHashSet clojure.lang.PersistentVector clojure.lang.PersistentList clojure.lang.PersistentArrayMap clojure.lang.MapEntry java.lang.Integer)

12:41 Chousuke: while yours would return (clojure.lang.PersistentList)

12:41 when the argument is #{['({1 2})]}

12:43 Chousuke: hmmh

12:46 oh well, you can still avoid the reverse by using a vector.

12:47 notsonerdysunny: yea you are right ..

12:47 Chousuke: the build-list-and-reverse is a CL idiom but it doesn't work in Clojure :)

12:47 tnoborio: In conclusion, I should understand that the rules should be one?

12:48 Sorry, bad english.

12:53 LauJensen: chouser: Judging from the fact that the resulting File object doesnt have a root path, the ctor call is equivalent to (File. "" "file"), so Im thinking nil gets a call from .toString

12:54 chouser: LauJensen: perhaps, but I think that would be dependant on the ctor itself.

13:01 edbond: enlive question: how to select ul > li, and li doesn't have class

13:01 "title"?

13:03 tnoborio: Japan time at 2am, good night.

13:03 edbond: answer: [:ul [:li (but :.title)]], cool

13:10 LauJensen: edbond: I think you left out the > ?

13:27 kumarshantanu: is there any short form for (if x x y) ?

13:27 jkkramer: kumarshantanu: (or x y)

13:28 kumarshantanu: jkkramer: omg, not sure how I missed that

13:28 * kumarshantanu slaps head

13:29 jkkramer: :)

13:40 jcromartie: If map is lazy, then "chaining" maps together has the effect of only iterating over the "base" collection once, right?

13:41 LauJensen: right

13:41 I mean, there's quite possibly some heavy sharing between the collections, but technically you're right

13:42 jcromartie: that's a *very* cool thing

13:42 LauJensen: technically, its *ubercool* :)

13:43 jcromartie: that makes doing any number of maps, essentially, O(N) right?

13:43 not quite

13:43 but close enough

13:43 where N is the size of the collection

13:43 not the number of maps

13:43 LauJensen: Not sure, Big O isnt my strong suit

13:49 jcromartie: well in a really pointless microbenchmark, I have to map over 1 million integers 5 times to double the running times of 1 map over them

13:51 ssideris: hi, I'm struggling with namespaces a bit

13:51 I'd like to use the Ellipse2D.Float class

13:51 so I have (ns mynamespace (:import (java.awt.geom Ellipse2D)))

13:52 and then I'm trying (Ellipse2D/Float. 10 10 100 100)

13:52 which doesn't work

13:52 it's a bit of an unusual one because it's a nested class

14:00 LauJensen: ssideris: nested classes are accessed with the $ operator, so outer$inner/method

14:00 ssideris: oh, thanks"!

14:03 so should this work? (new Ellipse2D$Float 10.0 10.0 100.0 100.0)

14:03 LauJensen: is Float a class?

14:03 Or a Method?

14:03 KirinDave: LauJensen: There is a boxed float class called Float, right?

14:03 ssideris: this is a Ellipse2D.Float class

14:03 LauJensen: no idea. But if its a class then (Ellipse2D$Float. 10.0 10.0 ...) should work

14:04 ssideris: this does not refer to the java.lang.Float

14:04 http://download.oracle.com/javase/6/docs/api/java/awt/geom/Ellipse2D.Float.html

14:05 I import (java.awt.geom Ellipse2D)

14:06 and (Ellipse2D$Float. 10.0 10.0 100.0 100.0) does not work

14:07 it's a very silly way to organise things... but that's how awt is...

14:08 LauJensen: ,(java.awt.geom.Ellipse2D$Float.)

14:08 clojurebot: #<Float java.awt.geom.Ellipse2D$Float@0>

14:09 edbond: LauJensen: works without :>, gladly

14:09 ssideris: LauJensen: thanks, that works :-)

14:10 it seems that if I don't qualify the name fully, it doesn't

14:11 LauJensen: ,(import '(java.awt.geom Ellipse2D$Float))

14:11 clojurebot: java.awt.geom.Ellipse2D$Float

14:11 LauJensen: ,(Ellipse2D$Float.)

14:11 clojurebot: #<Float java.awt.geom.Ellipse2D$Float@0>

14:11 LauJensen: edbond: it will work, but it can leak

14:11 Thats the whole point of >

14:13 ssideris: Did you catch that last import?

14:16 ssideris: thanks

14:17 as soon as I feel like I have a good grasp of namespaces, I think I'll sit down and write a tutorial about it

14:17 explaining everything in huge detail

14:18 LauJensen: You have namespace problems as well ?

14:19 ssideris: i just find use/require/import a bit confusing

14:19 and I think that the current documentation does cover all points

14:19 but a "for dummies" article would be good

14:21 LauJensen: import is for java classes. use is like require, but it interns all the functions from the namespace your importing in to your current namespace. require does not intern, but supports the :as keyword, (:require something [name :as anothername]) so you can run (anothername/somefn) ...

14:22 ssideris: yes I have worked out all this by reading here and there and looking at examples

14:23 but I didn't find all this covered in one place

14:23 especially the :as syntax

14:23 i remember looking at code in github, the official api reference, and the wikibooks clojure book to gather all the information i needed

14:24 LauJensen: ,(doc require)

14:24 clojurebot: "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of Cloju

14:25 LauJensen: try that in your own repl, there's a lot of info

14:27 ssideris: yes, I've seen this, but I think every case mentioned could benefit from a concrete examples... it would be particularly helpful for novices

14:28 LauJensen: Well, the last 2 lines are

14:28 Example :

14:28 (require '(clojure zip [set :as s]))

14:28 more complaints you need us to take care of tonight? :)

14:29 ssideris: look, this is not meant as ill-willed critisism, I greatly appreciate how helpful you guys are in the irc channel (and everywhere else)

14:30 LauJensen: I know, Im just yanking your chain a little :)

14:30 ssideris: I'm just saying that (possibly because I'm being a bit thick) I found namespaces a bit tricky to understand

14:31 so as a way to give back, I think I'll try and write something about when I feel a bit more confident

14:31 LauJensen: No no, I didn't mean to write this off as being easy to grok, Im just saying that the specific info you needed was actually in the require doc-string. I don't know where you could have learned about the $ operator

14:31 ssideris: $ is actually mentioned in the java_interop documentation :-)

14:34 LauJensen: Well there you go then, Rich takes care of us

14:40 ssideris: in Rich we trust

14:41 LauJensen: Well, no, we review the commit stream :)

14:44 ssideris: haha

14:50 ataggart: what is the incantation needed for lein to pull the 1.2.0 compatible contrib jar?

15:16 kumarshantanu: I want to understand how does this work: (def x #(println "foo")) ((var x)) ((ref x)) ;; var and ref work, but atom doesn't

15:17 what's surprising here is, they don't need a deref @

15:20 hiredman: in a time long ago vars and refs were the same thing

15:21 kumarshantanu: hiredman: I am intrigued why don't they need a deref

15:22 hiredman: because vars usually hold functions it is useful to have them implement IFn and just pass calls along to the object they hold

15:23 kumarshantanu: hiredman: ditto for ref? why not for atom?

15:23 hiredman: no

15:23 as I side vars and refs used to be the same thing

15:23 said

15:24 refs just sort of kept that behaviour, I don't know that you can rely on it continuing to be there

15:25 atoms where created fairly late, after the seperation had already occured so they didn't pickup that piece of left over code

15:27 kumarshantanu: even more curiously, ((var (var x))) and ((var (ref x))) don't work

15:27 hiredman: uh

15:28 kumarshantanu: but ((ref (var x))) and ((ref (ref x))) work fine

15:28 hiredman: clojurebot: special forms

15:28 clojurebot: Gabh mo leithscéal?

15:28 hiredman: clojurebot: jerk

15:28 clojurebot: I don't understand.

15:28 hiredman: clojure.org/special_forms

15:28 read the docs before asking a million questions please

15:32 kumarshantanu: hiredman: okay, and thanks for the pointer

15:33 Chousuke: kumarshantanu: the ref and var operators look like they're related but they do completely different things :P

15:34 the way to create a var named foo holding value bar is... (def foo bar)

15:38 kumarshantanu: Chousuke: I think I am getting it now, but I was surprised in the beginning :)

15:39 hiredman: ref is function and var is a special form that the reader macro #' turns into

15:41 Chousuke: I had no idea that the redirection feature of refs was just a leftover though.

15:43 kumarshantanu: ref seems to be transparent while acting on functions -- ((ref (ref (ref x)))) works

16:02 LauJensen: hmm, no ring/ring-core has been there for quite some time

16:05 bobo_: hm, any project that uses enlive? want to read some source to better understand how i should use it

16:06 LauJensen: bobo_: bestinclass.dk

16:06 bobo_: ah! should have known :-)

16:07 LauJensen: There are 2 things you can check out. 1) the wordpress import, which uses the selectors, and 2) the site generator which uses templates

16:07 clojurebot: google github bestinclass.dk

16:07 clojurebot: First, out of 166 results is:

16:07 LauJensen&#39;s Profile - GitHub

16:07 http://github.com/LauJensen

16:07 LauJensen: well, close enough

16:08 bobo_: think its mostly the templating i want to read up on now. so il check the site generator

16:08 LauJensen: k, I think the file is called templates.clj

16:08 bobo_: yeh looks like it

16:11 seangrove: What's the easiest way to start generating charts with clojure?

16:12 I've just lost ~1 hour messing around with the outdated dejcartes

16:12 bobo_: think i saw a jfreechart wrapper somewhere

16:13 ah, that was dejcartes :-p

16:13 seangrove: incanter perhaps?

16:14 seangrove: heh, yeah, I'm wondering about just using incanter

16:14 Sounds good, I'll give it a shot

16:14 It just looks like it might take more than an hour to get something up and running

16:14 Happy to give it a try though

16:22 LauJensen: seangrove: the easiest way is without a doubt Google Charts, close second is JFreeChart

16:26 ApeShot: every time I take a break from clojure for a few months, I come back and can't remember/figure out where and how everyone is (has to?) set up their project folders so that things will work. Is there a place in the documentation I am missing for how clojure searches and loads classes/clj files?

16:26 seangrove: What's the "hello world" of an incanter project setup with leinigen?

16:27 ApeShot: For instance, if I put a clj file which creates a namespace in the lib folder of a swank project, I can't (use 'x) it, but I can if I put the same file in src

16:27 Does lib only contain jars?

16:27 technomancy: ApeShot: there are no hard and fast rules, but the convention says that yes, every jar in the lib directory will be put on the classpath

16:28 ApeShot: have you read the Leiningen tutorial? it should help you get through that stuff.

16:28 clojurebot: leiningen tutorial?

16:28 clojurebot: paredit tutorial is http://p.hagelb.org/paredit-outline

16:28 technomancy: clojurebot: botsmack!

16:28 clojurebot: clojurebot evades successfully!

16:28 technomancy: ...

16:29 clojurebot: leiningen tutorial is at http://github.com/technomancy/leiningen/blob/master/TUTORIAL.md

16:29 clojurebot: In Ordnung

16:30 ApeShot: technomancy: Thanks. This looks ultra helpful.

16:30 * seancorfield loves leiningen :)

16:30 ApeShot: technomancy: I guess the source of this question is thus: I work on several projects, and each wants to use an sort of continuously evolving set of libraries.

16:30 technomancy: ApeShot: look for the "checkout dependencies" feature

16:30 seancorfield: lein new myproject; cd myproject; lein deps

16:31 technomancy: ApeShot: can't remember if it's in the tutorial or the readme, but it's designed for that use case

16:31 bobo_: technomancy: is that documented somewhere? except for its existance

16:31 ApeShot: technomancy: ok

16:31 technomancy: bobo_: lightly-documented, I think

16:31 but on the other hand, there's not a lot to it; it's easy to set up and should just work.

16:32 seancorfield: "If you create a directory called checkouts in your project root and symlink some other projects into it, Leiningen will allow you to hack on them in parallel. That means changes in the dependency will be visible in the main project without having to go through the whole install/switch-projects/deps/restart-swank cycle"

16:32 README > FAQ

16:33 ApeShot: seancorfield: So by this technique, I should create a "apeshotlib" project, even if I never hack on it directly.

16:33 And symlink it into checkouts

16:34 technomancy: ApeShot: right; in most cases you have one project that depends on all the others.

16:34 if you don't, you can create a dummy project

16:35 * technomancy ponders releasing 1.3.1 tomorrow

16:36 thunk: Is there a way to get slime to track buffers' namespaces from the (ns ...) form?

16:36 technomancy: thunk: C-c M-p should do it

16:37 thunk: technomancy: Ahh, very nice. Thanks

16:39 technomancy: np

16:47 ApeShot: Ok, so I put the symlink to the library project in checkouts, but how to I (use '...) a library defined there?

16:47 I am not sure what path-thingy to specify in the use command (or require, etc)

16:49 technomancy: ApeShot: that depends on the library. for contrib's io namespace you would have (ns apeshotlib.core\n :use [clojure.contrib.io :only [reader writer]]) ;; etc.

16:51 ApeShot: Not quite what I mean - suppose I create the apeshot lib, and in it lives src/error.clj which creates an (ns error)

16:51 How do I refer to that namespace from within another project?

16:51 after I have symlinked apeshotlib in checkouts

16:51 technomancy: firstly it should be src/apeshot/error.clj

16:52 ApeShot: Yes, that was my next question

16:52 And then it should be (ns apeshot.error)

16:52 In the file itself?

16:52 technomancy: right

16:52 and then if you have only a few functions you should put :use [apeshot.error :only [fn1 fn2 fn3]] in the ns form you're using it from

16:53 ApeShot: technomancy: I think I get it all now.

16:53 technomancy: thanks!

16:53 technomancy: if you've got more (or if you foresee adding more) you could do :require [apeshot.error :as error] instead; which means everything you use from that lib would have to be prefixed: error/fn1 error/fn2 etc

16:53 sure

16:54 ApeShot: I guess all this project discipline pays off in the long run.

16:54 I am sort of used to just hacking, starting with a "scratch.py" or whatever.

16:54 And gradually building up what structure a project needs

16:54 I suppose I could do that here.

16:55 But then it would be hard to use SLIME to its fullest.

17:07 technomancy: Man, it's too bad Relevance isn't secretly working on an in-house Clojure web framework, huh?

17:07 * technomancy catches up on the mailing list.

17:07 LauJensen: technomancy: ?

17:08 technomancy: LauJensen: just a silly thread on the mailing list

17:08 http://groups.google.com/group/clojure/browse_thread/thread/32c51ca7ebdbc154

17:08 * thunk detects a joke

17:08 LauJensen: ah

17:09 ApeShot: Ok, so I've fixed up the library project so that, for isntance, error is located in src/apeshotlib/error.clj and it creates a namespace (ns 'apeshotlib.error). If I start swank in the project directory, I can, for instance, (use 'apeshotlib.error)

17:09 technomancy: ApeShot: no quote in (ns apeshotlib.error)

17:09 ApeShot: technomancy: right, type

17:09 typo.

17:09 Ok, so in another project, I create a checkouts folder, symlink the apeshotlib project directory, start swank

17:09 How do I access apeshotlib.error?

17:10 bobo_: technomancy: al you know is that they dont admit that they are doing something secret! ;-)

17:10 ApeShot: (use 'apeshotlib.error) doesn't work, saying it can't find apeshotlib on the class path.

17:10 Do I symlink the lib project folder in checkouts, or do I symlink the apeshotlib folder under src?

17:11 technomancy: it should be a symlink of the project root

17:11 bobo_: true! stu is a sneaky guy.

17:12 chouser: not even that -- we know they don't admit that their secret project is a web framework. This simply raises the question: what *is* their secret project?

17:12 bobo_: oh! *plot thickens*

17:12 ApeShot: technomancy: that is how I have it now.

17:12 somnium: isn't the main unsolved problem in CS these days creating a web framework better than rails?

17:12 chouser: heh

17:13 technomancy: somnium: as long as we've solved naming things and cache expiry.

17:13 naming things: just don't use *jure, and you'll be fine

17:13 cache expiry: use memoize! it'll be simple.

17:13 problems solved. next!

17:14 ApeShot: technomancy: do I have to do something with apeshotlib's project.clj file?

17:15 technomancy: ApeShot: shouldn't be necessary. what does lein classpath show in the top-level project?

17:16 if apeshotlib/src isn't in there then it's not going to work.

17:16 ApeShot: could it be a problem with relative symlinks? try an absolute one maybe?

17:16 ApeShot: It shows apeshotlib/src

17:17 So maybe it is the relative/absolute symlink thing

17:17 Or maybe swank-clojure-project isn't grabbing the classpath?

17:17 The emacs command `swank-clojure-project`, I mean.

17:17 technomancy: yeah, that wouldn't work

17:17 ApeShot: Ah

17:18 technomancy: checkout dependencies are a leiningen feature, not an Emacs feature

17:18 ApeShot: So what is the right way to start a slime session from a leinigan project?

17:18 technomancy: so you need to do "lein swank" + M-x slime-connect

17:19 ApeShot: lein swank is not a task, apparently?

17:19 bobo_: ApeShot: you need :dev-dependencies [[swank-clojure "1.2.1"]])

17:20 ApeShot: bobo_: thanks, just read that in the FAQ

17:20 bobo_: (and then lein deps)

17:20 technomancy: or if you are on Leiningen 1.3, you can place the swank-clojure jar in ~/.lein/plugins to have it available for all projects

17:21 ApeShot: This is actually pretty sweet.

17:22 technomancy: yay \m/

17:22 bobo_: hm, is it only me who thinks it sounds nice to have a lein plugin to add other projects to a project?

17:23 ie, that symlinks and so on

17:23 except it isnt realy any so on

17:23 technomancy: bobo_: lein-search can add to project.clj

17:24 bobo_: cool

17:24 ApeShot: Everything seems to be working now - thanks everyone.

17:25 technomancy: bobo_: actually if you open the pom inside a lein-created jar it will show the git repo and SHA1 from which the jar was created.

17:26 you could totally use that to check stuff out into checkouts/

17:26 bobo_: intresting

17:57 seancorfield: technomancy: any thoughts on incorporating some of the more popular plugins directly into lein?

17:57 technomancy: seancorfield: yeah, lein-search may go into 1.4

17:58 seancorfield: any thoughts about lein-run?

17:58 technomancy: also a candidate

17:59 I think those might be the only generally-applicable ones

17:59 possibly lein-multi, but 1.4 is probably too early for that

17:59 danlarkin: lein-awesome

17:59 technomancy: danlarkin: that's already built-in!

17:59 no need for a plugin

18:00 danlarkin: touché!

18:00 seancorfield: hmm, i thought i had lein-run in my current test project but i don't and now i can't find it *sigh* time to google again

18:01 technomancy: seancorfield: upgrade to lein 1.3 and add it to ~/.lein/plugins

18:02 kumarshantanu: seancorfield: Lein-run 1.0.1-SNAPSHOT has a default alias too -- http://github.com/sids/lein-run

18:02 seancorfield: it doesn't create ~/.lein by default does it?

18:03 kumarshantanu: seancorfield: not sure abt ~/.lein

18:04 technomancy: seancorfield: no, that's all manual right now

18:04 yet another planned 1.4 feature

18:05 seancorfield: 'k... mkdir -p ~/.lein/plugins and a few cp later i'm in business :)

18:06 i put robert/hooke in there too

18:06 technomancy: indispensible chap

18:08 seancorfield: if i have a task in {project}/leiningen, it doesn't show up in the basic lein list of tasks - is that right?

18:08 i can run the task and lein help mytask shows the docs from the task

18:08 technomancy: it should be src/leiningen/mytask.clj

18:09 seancorfield: yes, it is

18:09 technomancy: oh... this may have been fixed in the 1.3.1-SNAPSHOT

18:09 seancorfield: it's actually hello.clj (and it prints hello world)

18:10 so i can do: lein hello

18:10 and: lein help hello

18:10 technomancy: we had some issues with missing nses due to a bug in contrib's find-namespaces lib

18:10 seancorfield: ah, ok

18:10 so lein upgrade ?

18:10 technomancy: upgrade will only get you the latest stable

18:10 you'll need to check it out and look at the build instructions at the bottom of the readme

18:10 or wait a day or two, hopefully

18:11 seancorfield: oh, ok... i'll just wait

18:11 i have a big website launch this week so i shouldn't be spending as much time on clojure as i am right now :)

18:11 post launch, that'll be another matter

18:11 technomancy: cool

18:12 actually it would be nice to get more help testing this since it's about to be released if you do have the time

18:12 seancorfield: 'k

18:13 * seancorfield goes to download the snapshot

18:16 * technomancy glances at the rest of the channel

18:16 technomancy: you guys too =)

18:16 I mean, if you've got a moment

18:17 somnium: is it a sign of over-use of printf-debugging when you use this? (defmacro quietly [& body] `(do (with-out-str (do ~@body)) nil))

18:21 technomancy: somnium: it could also be a sign of the fact that c.c.logging doesn't let you set log level at runtime. =\

18:22 seancorfield: ok, pulled, built... now where do i put the 1.3.1 snapshot jar?

18:23 do i just update VERSION at the top of the lein shell script?

18:23 or is there some magic lein command now i have the new jar?

18:26 ataggart: technomancy: I'm about to upload a version of c.c.logging that does

18:27 * somnium is about to download the new version of c.c.logging

18:28 ataggart: well it's not up yet :)

18:29 * seancorfield has leiningen-1.3.1-SNAPSHOT-standalone.jar but doesn't know what to do with it :(

18:29 ataggart: and for some reason the generated docs are a mish-mash of old and new names

18:33 seancorfield: figured it out... copied it to my maven repo manually and then copied the new lein script to /usr/local/bin

18:33 and i seem to be in business

18:33 my hello task still doesn't show up in lein help tho' :)

18:38 i'll have to update my laptop to lein 1.3.1 as well today

20:07 ssideris: ,(String/format "%02d" 4)

20:07 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to [Ljava.lang.Object;

20:07 ssideris: hm

20:12 dnolen: ,(String/format "%02d" (to-array [2]))

20:12 clojurebot: "02"

20:12 boojum: ,(format "%02d" 4)

20:12 clojurebot: "04"

20:25 dberg: (require 'clojure.contrib.str-utils) throws a file not found exception

20:27 I installed closure from ubuntu repo and followed the instructions to compile clojure-contrib

20:28 any steps I'm missing for clojure-repl to load str_utils?

20:36 dnolen: dberg: are you using clojure 1.2 ?

20:36 dberg: dnolen: no, the one in the repository is 1.0

20:36 dnolen: should I remove it and install 1.2 instead?

20:37 dnolen: dberg: yeah, I would. In 1.2 you can just (require '[clojure.string :as string])

20:39 dberg: dnolen: ok, cool, will do that. also noticed that although building clojure-contrib is successful there's an error in the beginning Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-sun-1.6.0.20/lib/tools.jar

20:39

20:44 dnolen: hmmm I didn't have jdk, installed, compiled clojure-contrib but no luck

20:44 dnolen: will try version 1.2

20:45 dnolen: dberg: so you have the jdk installed now?

20:46 dberg: dnolen: yes

20:47 emh: why doesn't the following print multiple lines?

20:47 (binding [clojure.pprint/*print-miser-width* 1] (pprint (range 10)))

20:49 ah. *print-right-margin* does what I want

21:00 alpheus: What project uses defprotocol? I'd like to read some code.

21:16 chouser: alpheus: http://github.com/Chouser/finger-tree/blob/master/finger_tree.clj

21:17 alpheus: thank you

21:18 Raynes: chouser: Did you ever get a chance to look at those yourkit snapshots?

21:58 chouser: Raynes: I downloaded them and then realized I didn't have yourkit installed.

21:58 I may get to them tonight or tomorrow.

21:58 Raynes: chouser: Alright, thanks. :)

22:53 chouser: Raynes: this is tough

22:53 irclj is one of the namespaces you reload?

22:57 hugod: is it the permgen space that is growing?

22:58 chouser: there are many more objects of many types

22:58 not sure if that answers the question.

22:58 hugod: i see permgen growth if I :reload anything with a deftype/defprotocol

22:58 chouser: but it's not just Class objects that there are more of

23:01 hugod: presumably, all the "old" objects hang around until they get GC'd

23:02 chouser: yeah, but I don't know that they'd be included in yourkit's list of objects

23:02 I guess I should confirm that before making assumptions.

23:02 hm, I wonder if MongoDB is keep a list of Connectors.

23:03 ...perhaps if they're not closed?

23:03 hugod: force gc, reload, force gc, and see what the difference is?

23:04 chouser: I don't have the code.

23:04 _mst: jvisualvm lets you diff two memory dumps too, if that helps

23:04 Raynes: chouser: Irclj is the underlying IRC library.

23:05 chouser: I'm looking at diffs between snapshots that Raynes took with yourkit.

23:05 Raynes: do you have any mongodb connectors that you aren't closing?

23:05 Raynes: I don't know. I open the DB in core, but I never reload core. I'm not sure how that magic works.

23:06 I can try disabling mongo completely and see what happens.

23:07 But to answer your question specifically, I never close anything. I just mongo! the db in core and then use it in plugins. I'm not sure what all of that is doing under the hood. It's all very implicit and magical.

23:08 chouser: I barely understand what I'm looking at here, but it does appear that mongo has a hashmap of Connectors, and thats one of the objects you have more of after a reload

23:08 I doubt it accounts for all of the increase, though.

23:09 Raynes: I appreciate you taking a look, either way.

23:09 I suck at profiling.

23:11 chouser: reference paths to things that there are more of, to see what roots may be hanging onto old values that you don't need.

23:11 but the scale of object allocation is hard to deal with.

23:12 Raynes: Taking out the mongo stuff has no effect.

23:12 chouser: after reload, you have 34 more array maps. But I don't know how to ask for the paths of any of those 34 from among the 3,180 array maps in total.

23:13 Raynes: Indeed.

23:14 It's a seriously annoying bug.

23:14 chouser: well, I don't think this is leading anywhere.

23:14 Raynes: I wish I knew how long it's been doing this. I never monitored memory usage when I first added reloading, so it could have been doing this all along and I didn't know.

23:15 chouser: I'd recommend trying to reproduce on a much smaller code base.

23:15 yourkit does say these are "live objects", so manual gc shouldn't be required.

23:16 so try something simple, with maybe just one lib. snapshot, :reload, snapshot, compare.

23:16 if even a simple case shows the problem, it'll be easier to get it accepted as a clojure bug.

23:16 Raynes: Yeah. It seems with even a single plugin this happens.

23:16 chouser: if a simple case does NOT show the problem, start scaling up until you see it.

23:16 Raynes: Just on a smaller basis.

23:18 I actually did a few tests to see if memory usage grew outside of sexpbot when libs were reloaded, but so far, I've not been able to nail anything down. I'll have to try some more difficult tests.

23:18 It could very well be, and probably is a sexpbot bug. I'm just clueless as to what could possibly cause such dramatic memory increases. I'll hunt it down eventually.

23:19 :>

23:19 chouser: I appreciate the advice, and I'll keep you posted on my findings. Thanks a lot for checking those snapshots out.

23:30 chouser: you're reloading at a REPL, or via an irc command?

23:46 Raynes: chouser: The latter.

23:48 chouser: If you want to check it out, the relevant function is reload-all! (disregard the bangs in some of the functions, I haven't bothered renaming them) in src/sexpbot/load.clj at http://github.com/Raynes/sexpbot. Any changes I've made since that last push in there should be minor and irrelevant.

23:48 I'm taking off for a little while.

23:48 technomancy: seancorfield: sorry; had to take off there

23:48 the answer is you don't have to do anything

23:49 just use the lein script from bin/lein in your checkout

23:53 Bahman: Hi all!

Logging service provided by n01se.net