#clojure log - Oct 26 2009

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

0:07 rlb: chouser: I think he's written a recursive func to do it -- see the link above.

0:07 (if I understand correctly)

0:09 technomancy: anyone want to test out a release candidate for slime that I'm going to submit to elpa?

0:09 chouser: ah, I see.

0:09 technomancy: http://github.com/technomancy/slime/tree/elpa open slime.el and M-x package-install-buffer; do the same w/ contrib/slime-repl.el

0:09 chouser: djork: you maybe be able to essentially wrap lazy-seq around the body of the function.

0:10 then use cons instead of conj and () instead of [] -- and you get a lazy seq that won't overflow the stack.

0:14 GenericUser1: Hello.

0:15 tomoj: technomancy: is it modified at all or just packaged for elpa/

0:16 chouser: GenericUser1: an appropraitly generic greeting. Welcome!

0:16 GenericUser1: I'm trying to learn clojure, and I'm having a bit of trouble figuring out the details of refs, agents, and vars. In particular, if I wish to refer to a ref from the value of another ref, is this safe to do?

0:17 Thanks :)

0:17 technomancy: tomoj: it's a slightly later version of trunk than the one that M-x clojure-install uses, but the only modifications I made myself were for elpa.

0:18 GenericUser1: To be a bit more concrete, I'm trying to model the states of various rooms, and I'd like to be able to keep a mapping of exits from one room to another, which may change at a later point in the room's existance.

0:18 chouser: GenericUser1: yes, a ref can contain a ref (though that would be a bit silly) or contain a collection ...

0:19 yes, a ref with a collection that includes another ref is perfectly safe.

0:19 GenericUser1: Ok. Is there any way I can stop the repl from evaluating circularly linked refs? :)

0:19 chouser: heh.

0:20 set your *print-depth*

0:21 sorry, *print-level*

0:21 (set! *print-level* 15) is what I usually use, though you may find that to be too deep or too shallow depending on what you're doing.

0:21 GenericUser1: ok

0:22 chouser: another option would be to store your rooms in a single top-level map, each keyed by some kind of unique identifier.

0:22 then instead of a ref pointing directly to another room, it could point to that room's key, avoiding direct loops.

0:23 GenericUser1: Ok.

0:23 Yes, that may be a nicer option.

0:23 tomoj: GenericUser1: I think there's an example of just that kind of program on github somewhere

0:24 yeah, http://github.com/technomancy/mire

0:24 technomancy: GenericUser1: gosh, that sounds awfully familiar... =)

0:25 tomoj: I have a similar problem trying to make representations of directed graphs

0:25 GenericUser1: Hmm, thanks.

0:25 technomancy: ?

0:26 technomancy: GenericUser1: the link tomoj pasted

0:26 GenericUser1: ah ;)

0:26 technomancy: it's a tutorial-type project of mine

0:28 GenericUser1: Does anyone else have problems with the API page in Firefox?

0:29 It seems that the page rendering gets cut off about half way down the list

0:29 tomoj: someone else complained about something like that before, too, I think

0:29 doesn't happen to me in any browser

0:31 GenericUser1: I'm in Firefox 3.5.3 on Vista, currently, although I've had issues with it on several other computers (I can't remember their configurations though).

0:31 Is there a good place to file a report about it?

0:32 technomancy: tomoj: I've got some ideas about the next version of swank-clojure if you've got a minute for feedback

0:32 (or anyone who's interested really)

0:34 tomoj: sure

0:35 GenericUser1: What is the meaning of "Experimental" in the API docs with regards to watchers?

0:35 technomancy: I'm going to submit swank-clojure as an elpa package too so it can depend on clojure-mode and slime

0:35 tomoj: GenericUser1: I guess it means it could change?

0:35 technomancy: and I'm trying to decide if I should get the Clojure code itself (Clojure, Contrib, and Swank) installed via git or some other mechanism

0:35 currently I'm leaning towards downloading jars into ~/.swank-clojure

0:36 but maven deps are also an option

0:37 tomoj: I dunno anything about maven

0:38 technomancy: I'm not really sure it supports this use case anyway

0:38 tomoj: by "downloading jars into ~/.swank-clojure" do you mean cloning the git and building like clojure-install does?

0:38 technomancy: (downloading dependencies without actually having a project checked out on disk)

0:38 tomoj: that seems fine to me

0:38 technomancy: I'm thinking downloading pre-build jobs

0:38 *jars

0:39 tomoj: oh, I dunno anything about that either :(

0:42 technomancy: tomoj: you mean you don't know if it's a good idea?

0:43 tomoj: I don't even know what a pre-build jar is

0:43 technomancy: just a jar that has been compiled by someone else

0:44 rlb: chouser: if you need to traverse a source collection and generate varying number of result items per-input, is that kind of lazy-seq approach one of the better ones in clojure?

0:44 technomancy: the only reason M-x clojure-install even performs a git checkout is that it was written before Clojure had turned 1.0

0:44 tomoj: oh, I thought "pre-build" meant it hadn't been built yet, english is funny :)

0:45 technomancy: hehe

0:45 I just want to reduce the number of working parts

0:45 tomoj: yeah I have had problems before with git/ant

0:45 technomancy: this would also make it a non-issue that OS X refuses to honor $PATH for gui-launched apps since git wouldn't be involved.

0:45 tomoj: and windows people have problems too I think

0:45 technomancy: that's like the #1 source of "bug" reports for me

0:46 tomoj: and if I want to use edge clojure I can just dump my own jars into .swank-clojure?

0:46 technomancy: yeah

0:46 tomoj: sounds good to me

0:47 technomancy: maybe have a defvar to tell it to look in a given dir so you don't have to manually drop the jars in there

0:49 chouser: rlb: depends on if you want a lazy seq or not, I suppose. If you don't, you'd have to convert your non-tail-recursive function into a tail-recursive one by adding an accumulator for your output collection (see "on lisp")

0:51 to avoid stack overflow, I mean.

0:53 rlb: Right -- I just didn't know if there was some clever clojure map-like function that I hadn't heard of yet.

0:53 (optionally destructuring map-like function)

0:54 GenericUser1: Is there a way to change how the print functions treat a value?

0:54 rlb: ...and I ask because it seems like often there often is some clever clojure function...

0:55 anyway, thanks.

0:55 piccolino: technomancy: was changing the checkout command the right fix?

0:58 technomancy: piccolino: it should be, though I don't understand why "git checkout clojure-1.0-compatible" failed

0:59 piccolino: did you catch the discussion above about removing the checkout/compile part and just downloading precompiled jars?

0:59 piccolino: Yeah, I don't either. Especially since it works for clojure itself. Is this not something that happens for you too?

0:59 I did see that. That sounds better, but I didn't know there was a pre-built release of clojure-contrib 1.0.

0:59 I asked about that in here about a week ago because I was trying to get a MacPorts portfile made for clojure-contrib.

0:59 technomancy: well I would build it and upload it myself; there's not an "official" one

1:00 piccolino: Oh, I see.

1:01 GenericUser1: Am I supposed to see stacktraces on exceptions?

1:02 I keep getting relatively useless errors saying things like Wrong number of args passed to <some function> (NO_SOURCE_FILE:0)

1:04 tomoj: GenericUser1: did you compile or just enter the functions into the repl?

1:05 clojure stacktraces seem to me to be generally more cryptic than some other languages

1:05 but your files should show up with line numbers if you do it right (e.g. C-c C-k with slime)

1:05 GenericUser1: At the moment, I'm calling a function in the repl that I loaded from a file

1:05 tomoj: how'd you load it?

1:06 GenericUser1: from the command line (DOS cmd)

1:06 piccolino: technomancy: let me know if I can help at all. Maybe if you put up a pre-built jar I can use that for MacPorts as well.

1:06 GenericUser1: java -cp clojure.jar clojure.lang.Repl model.clj

1:06 tomoj: hmm

1:06 technomancy: piccolino: I'll be sure to announce on the mailing list

1:06 piccolino: Thanks.

1:07 The clojure mailing list, right?

1:07 technomancy: piccolino: yup

1:07 piccolino: k

1:07 technomancy: man... maintainership is a lot easier once you realize you can respond to patches with "this looks great; can you rebase cleanly on top of my latest?" =)

1:07 instead of merging yourself.

1:07 GenericUser1: I also get very cryptic errors when I screw up using derive

1:08 For example, if I do something like (derive :foo :bar) instead of (derive ::foo ::bar), I get the error "Assert failed: (namespace parent) (model.clj:0)"

1:08 tomoj: I don't even get stacktraces or NO_SOURCE_FILE at all with clojure.lang.Repl

1:09 GenericUser1: (Not that I'm any stranger to cryptic errors... I've spent a enough time dealing with templates in C++ ;))

1:10 tomoj: are you happy using the repl from cmd? O_o

1:10 chouser: GenericUser1: (.printStackrace *e)

1:10 technomancy: piccolino: are you the David Santiago that emailed me about this contrib problem, or was that just a random coincidence?

1:10 piccolino: One and the same.

1:10 chouser: GenericUser1: (.printStackTrace *e)

1:10 GenericUser1: I've been going back and forth between cmd and Clojure Box emacs

1:10 But I don't know emacs at all, so emacs is constantly getting on my nerves :)

1:10 technomancy: piccolino: ok cool, I will delete this email then. =) thanks for the heads up.

1:11 piccolino: technomancy: No problem. Just trying to help out a little.

1:11 technomancy: piccolino: yup... too many moving parts right now.

1:11 tomoj: ah

1:11 technomancy: hard to find a moment to sit down and make sense of it all right now though

1:11 piccolino: Yeah, I still can't believe how young clojure is.

1:11 tomoj: GenericUser1: learning emacs is a good investment :)

1:12 GenericUser1: (When I keeping doing things like ctrl-z and it minimizes, and ctrl-f and it just moves forward one character, and ctrl-s and it tries to search instead of save... I get annoyed :p)

1:13 Yes, I know I should learn it, and I'm slowly learning pieces, but years and years of programming in various Windows editors has trained me with lots of things that I haven't yet unlearned.

1:14 *trained me to do lots of things that I havent' yet unlearned

1:14 yay grammar!

1:14 technomancy: unlearning is often harder than learning

1:15 GenericUser1: indeed.

1:18 piccolino: I also think Emacs could make a little more effort to blend in with what have become the widespread UI conventions over the past few decades.

1:18 But then that's why I use Aquamacs.

1:19 * technomancy wishes the past few decades' widespread UI conventions would take a little more effort to learn from Emacs

1:19 technomancy: but that's why I browse with Conkeror. =)

1:20 tomoj: I use conkeror too but I wish it were written in clojure

1:20 been investigating embedding gecko or webkit in java but I can't get anything to work

1:20 GenericUser1: Hrm

1:21 technomancy: tomoj: it's useless without access to the DOM

1:21 very few if any engines expose that in anything other than JS or C++. =(

1:21 tomoj: I would hope javaxpcom gives you that

1:21 GenericUser1: So, I have an agent 'john'... and when I do (@registry (:location @john)), it gives me the result I want, but if I do (-> @john :location @registry), I get the core$deref error

1:22 technomancy: ah... possibly.

1:22 GenericUser1: What am I doing wrong?

1:25 Oh... but if I don't deref registry, then I get it works again.

1:26 tomoj: I bet it's trying to do (deref (:location @john) registry)

1:26 GenericUser1: Hmm... Does that mean that -> treats @registry as (deref registry) and is really doing something like (deref (:location @john) registry)?

1:26 ah

1:27 tomoj: but a ref used as a function automatically derefs itself

1:27 maybe this is why?

1:27 so e.g. you can do just (registry (:location @john))

1:27 GenericUser1: Ah

1:27 tomoj: or even (registry (john :location))

1:28 == (-> :location john registry)

1:28 GenericUser1: So, it auto-derefs a mutability type if it's used as a function?

1:28 I've been wondering about that,

1:28 since if I have something like (:location john), I get nil

1:28 but (:location @john) --> correct answer

1:28 tomoj: I think clojure.lang.Ref implements the interface for functions and invokes whatever the ref points to

1:29 GenericUser1: huh, ok. Thanks.

1:29 tomoj: e.g.:

1:29 (let [foo (ref 3)] (foo))

1:29 ,(let [foo (ref 3)] (foo))

1:29 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

1:30 GenericUser1: I have maps in my refs and agents

1:30 ,(let [foo (ref {})] (foo))

1:30 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: PersistentArrayMap

1:30 tomoj: yeah, so invoking a ref/agent to a map will invoke the map

1:30 GenericUser1: ,(let [foo (ref {:a :b})] (foo :a))

1:30 clojurebot: :b

1:30 GenericUser1: there

1:30 ok

1:31 tomoj: also:

1:31 ,@john

1:31 clojurebot: java.lang.Exception: Unable to resolve symbol: john in this context

1:31 tomoj: err

1:32 ,'@john

1:32 clojurebot: (clojure.core/deref john)

1:32 tomoj: so -> sticks the previous value in the middle there and screws things up

1:33 GenericUser1: ,(-> @john :location '@registry)

1:33 clojurebot: (clojure.core/-> (clojure.core/deref john) :location)

1:34 GenericUser1: I'm not really sure what I just did there. O_o

1:35 Where did (clojure.core/deref registry) go?

1:36 ,(quote a b)

1:36 clojurebot: a

1:36 tomoj: you quoted it

1:36 GenericUser1: Ah, I see.

1:37 tomoj: so (quote (deref (:location (deref john))) (deref registry)) I guess

1:37 GenericUser1: I wonder when we'll see an obfuscated clojure contest :P

1:37 Yeah, so quote's dropping the deref registry, and just returning the first thing

1:37 ,(quote (deref (:location (deref john))) (deref registry))

1:37 clojurebot: (deref (:location (deref john)))

1:37 GenericUser1: yep

1:38 tomoj: that is pretty odd

1:40 just found this at imagine27.com

1:40 ,((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))

1:40 clojurebot: ((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))

1:40 tomoj: hah, crazy

1:40 GenericUser1: O_o

1:40 arsatiki: cool

1:41 GenericUser1: Nice quine.

1:41 chouser: (-> @john :location (@registry))

1:41 tomoj: aha

1:41 chouser: (-> :location (@john) (@registry))

1:42 not sure either of those are better than (@registry (:location @john))

2:41 GenericUser1: What's the proper way to specify custom exception types in clojure?

2:48 tomoj: if you want a custom exception type I think you need to gen-class it

2:49 or proxy

2:49 GenericUser1: I assumed that was the case, but I can't seem to get it to work right. Could you give me a quick example? I keep getting errors about the class not existing.

2:50 tomoj: well gen-class only does anything when compiling

2:55 GenericUser1: How do I compile this then? :P

2:56 If I try to do (compile 'model) I get an error about "can't find the path", and "model.clj" instead of 'model gives a type error (can't cast string), and I can't load the file (Can't find my custom exception class, because it hasn't been generated...)

2:57 At this point, I think it'd be easier to just write the damned exception class in Java :P

2:57 tomoj: well

2:57 what's your classpath?

2:57 G0SUB_: hmm, how do I get new agents to work after I have called (shutdown-agents) once? do I have to re-launch the JVM?

2:58 tomoj: if your file is model.clj, the path to the directory that model.clj is in should be in your classpath

2:58 GenericUser1: I'm just running everything in the same directory at the moment, with the one file model.clj from the command line

2:59 starting the repl with the same command as before;

2:59 tomoj: yes, but is that directory in your classpath?

3:00 GenericUser1: *shrug*

3:01 I don't think I've explictly put it there

3:01 tomoj: if you're doing like -cp clojure.jar, try -cp clojure.jar:.

3:01 GenericUser1: I just tried that, but same thing.

3:01 or actually, I used ;

3:01 I'm on Windows

3:02 : gives me NoClassDefFoundError for clojure/lang/Repl :P

3:03 I think I will just try to write the exception in Java and see if I can load that.

3:04 tomoj: adding . to the classpath didn't help?

3:04 GenericUser1: It didn't seem to

3:04 Unless I am misunderstanding what I was supposed to do after that

3:05 tomoj: (compile 'model)

3:05 that gives some blah blah.clj not found?

3:07 maybe the problem is that you're not supposed to have namespaces with only one segment?

3:07 I dunno

3:07 GenericUser1: java.io.IOException: The system cannot find the path specified (model.clj:5)

3:08 I've tried it with and without namespaces

3:08 tomoj: that's odd

3:08 GenericUser1: (ns model) at the top

3:09 line 5 of my file doesn't make much sense for the error either, since it's just " (dosync "

3:09 Unless :5 is supposed to mean something else ?

3:09 O_o

3:20 Well, I finally got it, using java classes.

3:22 I wrote an empty class 'CantMoveThatDirection' that extended Exception

3:22 put it in package model

3:22 then did

3:22 (import '(model CantMoveThatDirection)) in my model.clj

3:22 keeping CantMoveThatDirection in ./model

3:22 no ns for model.clj at the moment

3:24 I think I've had enough hacking on this for the time being though.

3:24 Thanks for the help. :)

3:24 cya.

4:51 AWizzArd: Moin

4:52 ~max people

4:52 clojurebot: max people is 191

4:52 AWizzArd: oho :)

5:12 elimisteve: I think I've found an error but I'm not certain http://pastebin.com/m59b6f7b1

5:13 At line 6, "user=>" should have shown up but didn't

5:14 Chousuke: elimisteve: I guess your erroneous string just confused the reader :/

5:18 elimisteve: Chousuke: yes but I still think I should get the prompt back after the exception, which is what has been happening until this particular error. More here: http://pastebin.com/m1b4c451d

5:22 Chousuke: yeah, the reader is a bit weird I guess.

6:06 esj: anybody mind a noob question on lazy sequences and memoization ?

6:06 if I have the following setue

6:06 (def base (atom '[1 2 3 4 5]))

6:06 (defn cumsum [coll]

6:06 (reduce (fn [o, i]

6:06 (conj o (+ (last o) i)))

6:06 '[0]

6:06 coll))

6:07 If I swap! the atom and deref cumsum is the entire lazy sequence reevaluated ?

6:07 say, (reset! base (conj @base 26))

6:07 (nth (cumsum @base) 5)

6:08 and then, in the case of a memoized cumsum, and the same swap! and deref, what is the behaviour ?

6:11 too early in the am I guess.... wake up America !

6:15 adityo: ~max people

6:15 clojurebot: max people is 192

6:21 tomoj: esj: if cumsum is memoized, it will return the cached result whenever you pass in something it's already seen

6:21 since you're passing in a deref'd value, I don't see where the confusion lies

6:21 esj: well, I just want to make sure

6:21 tomoj: if you did (cumsum base), and cumsum was memoized, that would be really bad

6:22 (and derefed inside cumsum)

6:22 esj: yes, I think I understand that

6:22 in the un-memoized case it does traverse the the entire calculation ?

6:24 I was just wondering, in the case of the memoized function, where, under the hood, Clojure noticed that @base was different, and hence the output of the function could be different

6:24 tomoj: naturally

6:24 the memozied cumsum doesn't know it's being passed a deref'd atom

6:24 it only sees the value

6:24 esj: excellent, this is terrific

6:25 tomoj: I don't think there is any auto-memoization

6:25 so if you don't memoize cumsum it will do the full calculation every time

6:25 (as far as I know)

6:25 esj: yeah, i figured it had to, or else it couldn't do the calculation

6:25 tomoj: clojure can't do automemoization like haskell would in some circumstances because clojure doesn't know whether your function is pure or not

6:26 esj: thanks for your help tomoj

6:28 how about something like (last coll)

6:28 how does it know its at the last element ?

6:28 ok, that's a stupid question, I take it back

7:34 avital: ,(+ 2 2)

7:34 clojurebot: 4

7:37 shmichael: Good afternoon I'm studying macros and have a question about the fundamentals. I wrote a simple macro that calls a function during macro expansion. I passed to it a parameter-less function, but it did not get called as expected. The code is as follows:

7:37 ,(defn j [] 0)

7:37 clojurebot: DENIED

7:37 shmichael: (defmacro log [f] (f))

7:38 (log j)

7:38 I recieve an exception: Wrong number of args passed to: Symbol

7:38 AWizzArd: and (f) outputs a list?

7:39 shmichael: no, a value

7:39 AWizzArd: You need to quote that list...

7:39 what if you do `(f) ?

7:39 avital: AWizzArd: I think shmichael wants the macroexpansion of (log j) to be 0

7:39 shmichael: What do you get when you run (macroexpand '(log j))?

7:39 shmichael: avital, you are correct

7:40 avital: I still get the exception

7:40 avital: I'm not sure why it's treating f within the macro as a symbol instead of as a function

7:43 shmichael: If i do: (defmacro log [f] (j)) then the macro expand behaves correctly

7:44 rhickey: a macro gets passed unevaluated forms, so (log j) is passed the symbol j

7:45 shmichael: Is there a way to "unsymbol" it?

7:46 avital: I think eval will work

7:46 something like (defmacro log [f] ((eval f)))

7:46 AWizzArd: When you have (defn j [] 0) and (defmacro log [f] `(~f)) and then call (log j) ==> 0

7:47 avital: AWizzArd: Yes, but the macroexpansion will still return (j) and not 0 as shmichael wants

7:48 shmichael: using ((eval f)) solves the problem

7:49 AWizzArd, avital, rhickey: Thank you

7:49 AWizzArd: Then maybe (defmacro log [f] (let [x# ((resolve f))] x#))

7:49 shmichael: Is resolve preferable to eval?

7:49 avital: AWizzArd: Oh yes, resolve also works, but why not just (defmacro log [f] ((resolve f)))

7:50 ,(eval '(+ 1 2))

7:50 clojurebot: DENIED

7:50 AWizzArd: shmichael: eval is expensive and should only be used when you write code at runtime.

7:50 avital: AWizzArd: His eval is running within a macroexpansion - it happens during compile time so it doesn't really matter

7:52 vy: Clojure complains that "Wrong number of args passed to: user$eval--2371$fn" for (swap! foo #(rand)) while (swap! foo (fn [_] (rand))) works without a problem. Shouldn't `swap!' allow functions with [& rest] arity?

7:53 jdz: RFC http://t-b-o-g.blogspot.com/2009/10/brians-brain-on-clojure.html

7:53 avital: vy: the second arg of swap! must be a function that gets at least one argument i believe

7:53 rhickey: vy: #(rand) is a function that takes no arguments, while (fn [_] (rand)) takes one and ignores it

7:53 avital: I think a function defined as #(rand) implicitly has 0 arguments

7:54 AWizzArd: vy: does (swap! foo #(do % (rand))) work?

7:55 vy: rhickey: I didn't know #() was counting arguments inside its body. Yup, (swap! foo #(let [_ %1] (rand))) works without a problem. Thanks.

7:55 avital: jdz: typo s/cojure/clojure/

7:55 rhickey: vy: (fn [_] (rand)) is much clearer though

7:56 jdz: avital: thanks!

7:59 tomoj: I would say (reset! foo (rand)) is even better

8:59 AWizzArd: rhickey: when I (deref *my-db*) and do this again, and no operations on *my-db* took place (reads are okay), will then = return instantly true?

9:00 that is, do the Clojure datastructures have some kind of version number under the hood that is used by =?

9:11 tomoj: no version number necessary

9:11 the value doesn't need to know it's the value of a ref

9:16 chouser: http://tinyurl.com/yhgdpyr -- Miditalk, a MIDI REPL from another era by our BDFL

9:19 tomoj: AWizzArd: but it seems list equivalence, at least, is linear

9:20 chouser: AWizzArd: I believe = on collections starts with 'identical?' so if it's unchanged should be very fast.

9:21 no version numbers in collections

9:21 AWizzArd: ok

9:21 tomoj: seems very fast, but not constant time

9:21 oh, constant if it's the same value

9:21 AWizzArd: ,(let [x (ref {:a 1, :b 2})] (identical? @x @x))

9:21 clojurebot: true

9:21 tomoj: er, identical value

9:22 AWizzArd: In my case x may contain some million k/v pairs.

9:22 And I need a diff. But before running the diff function I would like to see if it is needed.

9:24 tomoj: = on anything starts with java ==, it appears

9:24 so if it's the very same object, it will be very fast, as chouser says

9:24 chouser: AWizzArd: don't use = then. Start with 'identical?' and if that fails then just do your diff.

9:24 tomoj: no need, I think

9:25 clojure/lang/Util.java L19 does this, it seems

9:26 chouser: yes, but if they're not identical it'll go off on a full walk of the collection looking for a difference (though I suppose it will short-circuit when it finds one)

9:26 any work it does there would be a waste, since the diff will have to do it again anyway

9:28 tomoj: ah, yes

9:28 I had this idea that collections kept some sort of hash or something so that non-identical but same-valued collections could be compared for equality quickly

9:28 I wonder where I got that idea, because it seems totally wrong

9:29 AWizzArd: 99.9% of the operations on *my-db* are reads. So, an extremly fast check for equality is helpful. identical? does the job, good.

9:29 And what is the L19 thing tomoj?

9:29 tomoj: basically = does an identical? check before it starts crawling the collection

9:30 AWizzArd: yes, i could use =, but it won't give me more information than a boolean value.

9:30 tomoj: I just meant that = is already fast on identical objects

9:30 AWizzArd: The only danger is that they are not identical.

9:31 tomoj: right

9:31 AWizzArd: while a full check is perfectly fine when the map contains a few hundred elements it may not be so nice if it needs to crawl through 5gb of data.

9:31 although this might average out on 2.5 gb then

9:32 tomoj: damn

9:33 what the heck are you doing with all that in memory?

9:34 AWizzArd: It's the db.

9:34 a 12 gb server costs only 100 Euro per month

9:34 ambient: im wondering if I'm doing something wrong when im implementing my own type-system

9:35 AWizzArd: Why should I use a lame sql db system when I can have everything in-ram and in Clojure? :-)

9:35 ambient: somehow mixing multimethods and macros could also work

9:35 tomoj: AWizzArd: the D in ACID?

9:35 AWizzArd: tomoj: full snapshots written on disk + transaction log.

9:36 tomoj: did you hack clojure's STM?

9:36 I didn't think that was possible

9:36 AWizzArd: Why hack?

9:36 tomoj: are you using watchers to write the snapshot?

9:37 AWizzArd: no

9:37 tomoj: when, then?

9:37 AWizzArd: you can have a (dosync ...) and then deref all your toplevel vars that contain the data.

9:37 This can be done within a millisecond. Then I have snapshots, and one agent can write them out to disk.

9:37 tomoj: sure, but if the plug is pulled after the dosync but before the snapshot is written? :)

9:37 AWizzArd: Clojure supports Multiversion Concurrency Control.

9:38 tomoj: transaction log

9:38 tomoj: same problem

9:38 fro0g: maybe slightly OT, but how does the IBM and Sun JVM compare?

9:38 AWizzArd: same with the db

9:38 a relational db system may also have the problem

9:38 tomoj: no, mysql for example is really ACID

9:39 AWizzArd: i can wait until my data is on disk for a transaction and only then proceed

9:39 but even mysql won't write it out and then check if everything was written correctly

9:40 it will pass the data to the disk controller, and when the controller has some time and is in the right mood, it will write out the data.

9:40 After the data was given to the controller there could be an electrical cut

9:41 tomoj: well

9:41 I don't actually know shit about mysql internals

9:41 AWizzArd: If I wanted I can write out to disk, read it back in and see if all arrived and only then proceed.

9:41 tomoj: but there are certainly some databases that are ACID compliant

9:41 no, you can't

9:41 AWizzArd: yes, mine :)

9:41 tomoj: because once the transaction completes, other readers will be able to read

9:41 unless you're single threaded?

9:42 AWizzArd: i don't have to update the main ref

9:42 chouser: need a disk sync or close the file between write and read or the OS will trick you

9:42 tomoj: otherwise you've got to have a lock that says "hey you can't read this yet because I haven't made sure it's on disk"

9:42 AWizzArd: The db has a version number. The server takes a snapshot and remembers its current version.

9:42 The server operates on the snapshot and only writes data back when needed to the global db.

9:42 All other readers would get the old version.

9:43 I can have many snapshots and then atomically update the db when all data arrived on disk.

9:43 snapshotting the whole db will take 1 msec

9:43 and this is not needed if the version number is still the same

9:43 also I said, 99% of the operations are reads

9:44 And those are much nicer with an in-ram db.

9:44 tomoj: yeah

9:44 guess you don't need fancy relational crap?

9:44 AWizzArd: query language: Clojure

9:44 right, I want Clojure objects

9:45 I don't say that my usecase is the right thing for every db job out there.

9:45 tomoj: is this open source? :)

9:45 AWizzArd: But it works for me.

9:45 No, not yet, but maybe next year.

9:45 tomoj: ah

9:45 I had one project where I wanted a whole bunch of clojure objects in memory all the time

9:46 AWizzArd: It can be nice for *some* apps. I don't say that my solution is the silverbullet and will revolutionize how apps are written. For me it works.

9:46 tomoj: hmm.. though now that I think about it after learning some couchdb, maybe couch would be better

9:46 I wonder how far I can push couch's mapreduce without making it explode

9:47 my project is also almost entirely reads

9:48 writes are like a whole bunch twice a year and then a tiny trickle the rest of the time

9:48 and for the two big writes a year, no one's reading while that's happening

9:49 maybe I should just keep it all in memory after all

9:49 AWizzArd: It's nice in those cases to not send requests over a socket, but instead just doing a hashmap lookup and have the final object delivered.

9:49 tomoj: I wonder, how long does it take to start up, though?

9:49 I mean, to read in the db from the snapshot on disk?

9:50 AWizzArd: This depends on many factors. If there is just one snapshot, without a transaction log, then the snapshot is read via (read).

9:51 The Clojure reader reads it in and everything is at the right place.

9:51 tomoj: I wonder how long (read) takes to read a GB or so

9:51 AWizzArd: You could write a hashmap to disk {1 1, 2 2, 3 3, ...} and try it.

9:52 tomoj: I don't have any spare ram here, I'll try when I get to my bigger computer

9:52 you should write a blog post or something about your system if it's not secret :)

9:57 AWizzArd: I think in-ram DBs will get more interesting, now that 4gb bars cost just 200 Euros.

9:57 Especially with Clojure it is so very cheap to work with snapshots.

9:58 rhickey basically solved the hardest parts of the problem already.

9:58 chouser: I still think it would be interesting to have a diff algorithm that exploits the internal tree structure of the collections

9:59 AWizzArd: Yesss

9:59 sounds very useful

10:00 chouser: this has been discussed before. one significant question is what this "diff" would look like -- how to capture all possible values and also describe dissocs

10:02 tomoj: maybe if I understood the trees clojure uses I would understand why that's useful

10:13 chouser: tomoj: http://groups.google.com/group/clojure/browse_thread/thread/cc316de16fcba6c8/a74e652eb98693ce#a74e652eb98693ce

10:14 tomoj: thanks

10:15 rhickey: hack of the week: http://github.com/richhickey/clojure/commit/6362e0f2522c4f7b2b2e626016b291d4832bb58a

10:16 all host interop uses reflection. but method bodies in defclass* need to do host interop with themselves and instances of their own class, which doesn't exist yet

10:17 so, first generate a stub class that derives from the same interfaces and has same fields, but does nothing, hint 'this' to the stub, lop off stub prefix in generated bytecode

10:17 chouser: ahaha

10:18 AWizzArd: hmm

10:18 oh

10:18 chouser: compile-time reflection lives on!

10:18 lisppaste8: rhickey pasted "look ma, no reflection" at http://paste.lisp.org/display/89293

10:19 rhickey: chouser: it won't in cinc, but changing the Java was just too much to take on now

10:20 but note that all of the auto-interface implementing can happen in defclass and deftype macros, not in Java

10:20 chouser: would it also have worked to create an object that implements the reflection interface and pretends to be like this stub?

10:20 rhickey: chouser: you can't because there are no interfaces for the reflection classes (Method etc), nor can you create instances of them!

10:21 chouser: gah. ok.

10:21 rhickey: the evils of concrete classes

10:21 chouser: in that paste you hinted 'this' in toString, but that's not necessary, right?

10:22 rhickey: right, not needed just a test

10:22 chouser: I think you said previously that cinc would use info from .class and .jar files instead of compile-time reflection. Is that still the plan?

10:22 rhickey: so the simple name of the class being defined will be an alias for the class being defined, in type hints, instance? etc

10:22 chouser: ah, right, so you can do #^Foo other

10:23 rhickey: chouser: it will use a Clojure-based representation of type info, disconnecting it from its source

10:23 #^Foo other, and self-type ctor calls will be very important

10:23 chouser: ok, so it might use .class files, reflection, or a stub like this as needed

10:24 well, not exactly like this, but info generated on the fly to solve this problem.

10:24 rhickey: chouser: exactly

10:25 tomoj: I wonder how many tech talks are as philosophical as rhickey's. enjoying http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

10:25 rhickey: so all that's left on the Java side is: needed - deal with return type covariant bridges, planned - a true switch construct

10:26 with the former, definition of deftype and defclass macros can proceed, the latter will be used to optimize field lookups

10:27 but will be a generally awesome object-based switch, useful with any constant objects like strings/symbols/keywords

10:27 chouser: the latter will be a implementation detail performance improvement, so is not blocking progress.

10:27 rhickey: chouser: right

10:28 chouser: so does that mean you're nearly out of excuses for avoiding the bridge methods?

10:28 rhickey: first impls of lookup as simple as: (valAt [k] (condp identical? k :a a :b b :c c))

10:28 chouser: I have the same excuse, pain, but nothing else to do first :(

10:30 defclass will be so much better than Java at (the better part of) Java

10:34 AWizzArd: Can I type-hint something as (primitve) bool?

10:34 rhickey: boolean

10:34 AWizzArd: thx

10:46 djork: defclass scares me

10:46 it seems like it might encourage people to write Java-style OO in Clojure

10:48 chouser: if they don't understand how to use the power of multimethods, they'll just use them to dispatch on the type of the first arg anyway

10:49 Chousuke: can you actually define your own methods with defclass? or just the stuff that the interfaces define?

10:53 * Licenser is excited, got his copy of programming clojure today :D

10:53 AWizzArd: djork: this OO style is not always very bad. And the alternative would be to use structs and dispatch on a :type slot. But this is not anywhere as efficient.

10:53 Chousuke: djork: I don't think you need to worry about that. As far as I can tell, you can only define immutable "data packages" and all the operations will actually be defined outside the class (as interfaces or protocols)

10:53 djork: so it's more for Java-Clojure interaction

10:54 Chousuke: djork: so it's not much like java at all. :P

10:54 djork: i.e. integrating Clojure with existing Java code

10:54 chouser: no, it's for high-performance Clojure

10:54 AWizzArd: For example, if you want to write a tokenizer, then in a production environment it would have to create millions of small token objects. This will be extremly much faster with simple native Java classes.

10:54 Licenser: will there be High Availability Clojure te?

10:54 to

10:54 AWizzArd: what chouser said

10:58 djork: AWizzArd: I'm not sure I understand. Why would creating a class address that tokenizing problem better?

10:58 Chousuke: djork: the object will be a lot smaller than a structmap instance.

10:58 djork: hmm

10:58 Chousuke: djork: and thus faster to create

10:58 djork: I see

10:59 well I'm all for a better Java than Java, and defclass appears to achieve that, but it just feels like *more Java* whereas the feeling I got from Clojure was *less Java*

10:59 Chousuke: I don't think it's so much about java than giving Clojure it's own way of defining such simple data structures

11:00 defclass should be fairly portable to any non-java host too.

11:00 its*

11:00 tomoj: the value-identity-state presentation makes me think that representing a directed graph as a bunch of refs which have lists of refs as their children is probably a bad idea

11:00 need to find a good persistent way to represent graphs

11:01 steiger: tomoj: why not use persistent hashmaps?

11:01 AWizzArd: Actually I wrote a lexer and use a Clojure struct. But my tokens are throw-away objects, only needed for the parser. I then exchanged the token struct with a Java class Token and it got a great speedup, because instantiation was much faster.

11:01 tomoj: steiger: because the graphs might have cycles

11:01 steiger: tomoj: if you ask me, i'd say it's a simple and elegant way to represent graphs. most importantly, simple

11:01 tomoj: so what?

11:01 Chousuke: tomoj: map of nodes to sets of nodes?

11:01 djork: so structmaps are slow

11:01 because they are generic

11:02 tomoj: so if there's a cycle... it won't work

11:02 :)

11:02 maybe I'm confused

11:03 Chousuke: tomoj: give each node an unique identity that you use as the key?

11:03 steiger: tomoj: {:1 [:2 3] :2 [:1]} . that would be a graph with a cycle

11:03 tomoj: Chousuke: yeah I guess that would work

11:04 and then you have to look up the data for a node in a separate place I suppose

11:04 Chousuke: yeah. or you can have {:1 [thenode #{:2 :3}] ...}

11:05 tomoj: oh, and then to get a node's child you just look up the key and take first, I see

11:05 oh, except I need data on edges too, hmm

11:06 {:1 [thenode theedge #{:2 :3}] ...} ?

11:06 no.

11:06 {:1 [thenode #{[anedge :2] [anotheredge :3]}] ...}

11:07 steiger: simple, eh? :)

11:07 Chousuke: hmm, that's not so easy to look up :/

11:07 steiger: tomoj: modeling graphs in computers needs planning. get a chalkboard and _think_ . it's pretty cool, designing that kind of stuff

11:07 tomoj: pretty easy when persistence isn't desired, I think

11:07 I was thinking of finding some papers on graphs in haskell and porting stuff

11:08 Chousuke: if you need that then {:1 [node-data {:2 edge-data12 :3 edge-data13}]}

11:08 AWizzArd: djork: struct maps are Persistent and offer a great bunch of features. Java classes don't.

11:08 steiger: tomoj: when i was doing a little graph library, i used {:node1 #{:node2 :node}} .... and i could add data about edges and node using metadata.

11:09 tomoj: hmm, that's an interesting idea

11:10 steiger: tomoj: something like: (def make-graph [graph] (something-to-check-the-entry-is-valid) (something-to-add-the-desired-metadata))

11:10 but, of course, there are tons of other ways to do that

11:10 that = represent graphs ;]

11:11 tomoj: I feel like my node/edge data doesn't really belong in metadata in principal, but it sounds simple to work with

11:11 s/principal/principle/

11:12 much better than the mess of refs pointing to refs pointing to refs I've got now

11:13 steiger: tomoj: yeah, i think refs are unnecessarily complicated to this kind of job

11:13 tomoj: huh there is a clojure.contrib.graph

11:13 steiger: tomoj: yeah... the approach clojure.contrib.graph uses is quite interesting, have a look

11:13 quite creative

11:14 tomoj: but don't give up, try to develop your own, too. clojure.contrib.graph has it's limitations ;]

11:17 duncanm: if i wanna have write a GUI project that can build into an executable JAR, but still get to implement it incrementally using SLIME, that means i'll have to write both an ant script and some sort of load script in Clojure, right?

11:19 tomoj: fns for children, creative indeed

11:22 ambient: duncanm i can develop swing apps perfectly fine with Emacs, just don't add any functionality to terminate the process when the window closes

11:22 duncanm: ambient: and when it comes time to deploy?

11:22 ambient: *shrug* :)

11:22 im sure i can make the whole thing a single JAR in that moment

11:23 duncanm: ambient: do you write all your code in a single file?

11:23 ambient: depends, how large it grows

11:23 i see no problem in deviding different functionality into their own files

11:24 duncanm: ambient: then how would you load it using emacs, other than writing some load script that calls load-file

11:24 ambient: you just call a function like (start-gui) and call dependencies in the file beginning like (ns my.gui.stuff (:use my.gui.stuff2)

11:25 duncanm: ah, that's another way, cool

11:25 tomoj: duncanm: curious, are you using swank-clojure-project?

11:26 duncanm: tomoj: i don't know of it

11:26 tomoj: you have clojure-mode?

11:26 duncanm: tomoj: i do, and i have SLIME

11:26 tomoj: then you should have either a swank-clojure-project or a clojure-project function

11:27 duncanm: tomoj: M-x shows me only swank-clojure-import

11:27 tomoj: ah, you probably need to upgrade

11:27 clojure-project is from the emacs-starter-kit I guess

11:27 duncanm: oh, i installed it using ELSA

11:27 ELPA

11:28 tomoj: well, if you upgrade, it makes it really easy

11:28 you put all your dependency jars (including clojure.jar and clojure-contrib.jar) into lib/

11:28 and all your source clj files into like src/com/foo/bar/baz.clj for ns com.foo.bar.baz

11:28 and then swank-clojure-project sets up the classpath and everything for you

11:29 unless you like managing the classpath manually, then that would just be annoying, I guess

11:29 duncanm: tomoj: i think i have the latest version of clojure-mode

11:29 tomoj: "latest" = from git?

11:29 duncanm: i think so

11:29 latest is 1.5

11:30 but i don't have emacs-starter-kit

11:30 tomoj: oh, swank-clojure-project is from swank-clojure

11:30 you need to update swank-clojure I guess

11:31 if you don't use anything besides clojure and clojure-contrib, I guess it provides no benefit

11:32 duncanm: tomoj: i can't find this, i have the latest swank-clojure from GIT

11:33 ahh

11:33 i see that defun now

11:33 tomoj: \

11:35 steiger: seems if you use metadata you either end up keeping a map with node ids as keys or using a vector to hold the node data anyway

11:36 unless maybe you can ask a map to give you a certain key?

11:39 if you go with chousuke's representation above, then getting all the incoming edges for a node is slow, you have to search the whole graph :(

11:45 ysmolsky: i have kinda dumb question. slime gives me cool auto-completition. is there a way to get such functionality for usual clojure edit buffer? i mean abbr works okay and all, but completition for java would be great.

11:47 tomoj: ysmolsky: if you figure it out let me know

11:47 :)

11:49 duncanm: tomoj: i don't get how M-x clojure-project works

11:49 ysmolsky: i see :)

11:49 duncanm: it wouldn't let me type at the Project Root prompt

11:51 yuras: tomoj: anyway, are you satisfied with abbr completition you have for clojure atm? ;)

11:52 tomoj: I don't have abbr completion

11:52 duncanm: tomoj: ahh, i'm using swank-clojure from someone else's github

11:52 tomoj: or if I do I don't know how to use it

11:52 duncanm: I use technomancy's

11:52 I believe it's swank-clojure-project nowadays

11:52 duncanm: right

11:52 i have jochu's

11:52 tomoj: if it won't let you type maybe you don't have ido working?

11:53 yuras: you should update all kind of modules like, slime, swank-clojure and clojure-mode

11:53 actually i make it work when i used clojure-install command from clojure-mode

11:53 it downloads all needed deps and configure things

11:55 duncanm: hmm

11:55 i have emacs 23 on windows

11:55 swank-clojure-project isn't working, or i don't know how IDO works

11:59 tomoj: how do you accept the project root?

11:59 that's my project right now

12:00 s/project/problem/

12:00 tomoj: type to the root of your project and press enter

12:00 e.g. I type ~/clojure/foo-project/ RET

12:00 maybe it doesn't allow you to choose that directory if it's not set up right

12:00 you should have a lib/ and src/ directory at minimum

12:01 and clojure.jar (and maybe clojure-contrib.jar) need to be in lib/

12:02 duncanm: tomoj: enter isn't working

12:02 it's something to do with locate-dominating-file

12:02 RET isn't working

12:04 tomoj: someone else had a problem like that before

12:04 didn't hear a solution

12:04 I think I have emacs 23 somewhere around here, I'll try it

12:05 (not windows though)

12:07 duncanm: tomoj: i took out the IDO part and now it works

12:07 maybe ido-* is broken on windows

12:08 tomoj: sounds terrible

12:08 unless you have a replacement, I guess

12:09 duncanm: hmm

12:09 swank-clojure-classpath's value is

12:09 ("c:/Projects/FileMonitor/src/" "c:/Projects/FileMonitor/lib/clojure-contrib.jar" "c:/Projects/FileMonitor/lib/clojure.jar" "c:/Projects/FileMonitor/lib/ij.jar" "c:/Projects/FileMonitor/test/")

12:09 so that's correct - but when i try to load a file (C-c C-l) it still couldn't find it

12:09 tomoj: what file did you try to load

12:09 also try C-c C-k instead

12:10 duncanm: i have src files under "c:/Projects/FileMonitor/src/"

12:10 but it couldn't see them

12:10 tomoj: a file that defines the namespace foo.bar.baz should be in src/foo/bar/baz.clj

12:10 duncanm: yeah, i have that

12:10 and it's saying it couldn't find foo.bar.baz

12:11 tomoj: well, C-c C-l works fine for me, strange

12:11 but try C-c C-k in a source buffer I guess?

12:11 duncanm: same deal

12:12 tomoj: C-c C-l works fine without swank-clojure-project?

12:12 duncanm: yeah

12:12 well, i didn't use the ns feature before

12:12 tomoj: that doesn't make sense to me

12:13 since it's doing the same thing it was doing before, swank-clojure-project just sets the classpath... /shrug

12:13 duncanm: and my listing of swank-clojure-classpath looks correct?

12:13 tomoj: yep

12:13 duncanm: if i have files c:/Projects/FileMonitor/src/com/example/Foo.clj

12:14 ambient: i use small text in clj files, like "foo.clj" myself

12:14 tomoj: I wouldn't think that would matter

12:15 duncanm: hmm

12:15 tomoj: what is the exact error when you C-c C-k

12:15 duncanm: tomoj: if i print out the classpath, it doesn't include my project dir

12:15 user> (println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))

12:15 (#<URL file:/C:/Users/Duncan/.jars/clojure.jar> #<URL file:/C:/Users/Duncan/git/swank-clojure/src/main/clojure/> #<URL file:/C:/Users/Duncan/git/swank-clojure/src/main/clojure/> #<URL file:/C:/Users/Duncan/.jars/clojure-contrib.jar> #<URL file:/C:/Users/Duncan/git/fiji/ImageJA/ij.jar>)

12:15 tomoj: did you kill your old slime repl before doing swank-clojure-project?

12:15 duncanm: lemme start from scratch

12:15 sigh, i'll restart emacs

12:15 tomoj: you need to ,sayoonara

12:16 swank-clojure-project wants to start a new repl and a new java process

12:16 duncanm: dum de dum

12:16 still no go

12:18 oooh

12:18 i was doing :use, maybe i should use :refer instead?

12:18 tomoj: :use should be fine

12:18 duncanm: tomoj: what did you suggest earlier? when i talking about load scripts?

12:18 tomoj: anyway that definitely doesn't matter if it can't even find the file

12:19 duncanm: oooh

12:19 i see this problem, maybe

12:19 when i do C-c C-k, the top of the output says

12:19 ambient: duncanm i got emacs 23 on windows and i do this in my .emacs: (dolist (d (list "c:/code/clj/penumbra/src" "c:/some/more/stuff")) (add-to-list 'swank-clojure-classpath d))

12:19 duncanm: cd c:/Projects/FileMonitor/src/edu/harvard/connectome/

12:20 so maybe it's going too deep into the directory tree

12:20 Unknown location:

12:20 error: java.io.FileNotFoundException: Could not locate edu/harvard/connectome/DownsampleImages__init.class or edu/harvard/connectome/DownsampleImages.clj on classpath: (FileMonitor.clj:1)

12:20 ahhh

12:20 ambient: sounds like the problem is in the classpath and how to set it right

12:21 tomoj: and you have a src/edu/harvard/connectome/DownsampleImages.clj?

12:21 duncanm: yeah

12:22 tomoj: then your classpath seems fine to me

12:22 maybe swank-clojure is setting it in the linux way

12:23 or some other windows problem is happening

12:23 I think those libraries are not tested much on windows

12:23 duncanm: (ns edu.harvard.connectome.FileMonitor

12:23 (:import (javax.swing JFrame SwingUtilities))

12:23 (:use DownsampleImages DownsampleXML)

12:23 (:gen-class))

12:23 ambient: is it a windows problem when a software assumes that there's a UNIX-like filesystem? ;)

12:23 duncanm: that's what i'm doing now

12:23 ambient: i always use the full name in :use, like amb.synth.engine etc..

12:24 hiredman: ambient: Yes.

12:24 tomoj: yes, try with the full name

12:24 Chousuke: the naming isn't very idiomatic either :/

12:24 duncanm: oooh

12:24 tomoj: you can use a prefix for having two of them

12:24 duncanm: okay

12:24 tomoj: so if i have edu.harvard.connectome.DownsampleImages, then that works

12:25 aha, now it works

12:25 tomoj: like {:use [edu.harvard.connectome DownsampleImages DownsampleXML]) I believe

12:25 Chousuke: usually a list, but either works

12:25 tomoj: and, yeah, we use lisp-case around here, not CamelCase :P

12:26 duncanm: seems like the only case that works is the full name, with no spaces

12:26 i don't mind having n lines of :use's

12:26 tomoj: oh, I think it's like

12:26 well, hmm

12:27 (:use (edu.harvard.connectome DownsampleImages DownsampleXML)) should work, right?

12:27 duncanm: tomoj: i like using lisp-case too, but i can't name my files that way, before DownsampleImages, it was downsample-images

12:27 tomoj: yeah, but that precisely did not work

12:27 tomoj: you can't name files using hyphens?

12:27 gerry_: hello

12:27 duncanm: i supposed i could have foo-bar, but then the filename needs to be foo_bar.clj

12:27 tomoj: why not foo-bar.clj?

12:28 duncanm: tomoj: it wouldn't find it

12:28 hiredman: tomoj: - is not legal in classnames

12:28 gerry_: will datatypes support inheritance just like oop?

12:29 tomoj: hiredman: nor package segments?

12:29 it certainly is.. clojure.contrib.repl-utils for instance

12:29 Chousuke: gerry_: what would you inherit? the fields? :P

12:29 hiredman: tomoj: the file is named repl_utils.clj

12:29 duncanm: ambient: so the key thing is not to use setDefaultOperation and make it EXIT_ON_CLOSE?

12:29 tomoj: hiredman: ah, I see

12:29 gerry_: chousuke: fields and methods

12:30 hiredman: clojure maps '-' in namespaces to '_' in file names

12:30 tomoj: good to know

12:31 duncanm: nice, now i can do the work in SLIME, and still build it into a jar with netbeans

12:35 gerry_: Chousuke: if i want add fields to some datatypes been defined?

12:35 Chousuke: hmm.

12:37 ambient: duncanm yes, i dont do that generally

12:37 duncanm instead i make my own window close listener and bind any operations i want to do into that

12:37 Chousuke: well, the classes won't have any methods, and can apparently only implement interfaces.

12:37 so you wouldn't be able to use defclass to derive from another class.

12:38 gerry_: Prototype-based oop such as javascript or Io seems not bad

12:38 Chousuke: any methods besides the ones the implemented interfaces require, that is.

12:38 The-Kenny: I want a port of CLOS to clojure :)

12:38 tomoj: why would we want prototype based oop?

12:38 Chousuke: clojure already has that anyway :P

12:38 just put stuff in maps :P

12:39 gerry_: hmm

12:40 ambient: i dont just use maps for classes, i also use them for type system :|

12:40 gerry_: can i just assoc datatype to get new datatype?

12:40 or something like this?

12:49 chouser: you could use macros to assemble larger datatypes out of smaller pieces.

12:54 duncanm: ambient: ping?

12:54 ambient: ack

12:55 djork: I bet this question has been beaten to death, but: rhickey: what kind of setup do you use to write Clojure code?

12:55 duncanm: ambient: i'm trying to redirect System.out to a JTextArea, and i'm just translating Java code to Clojure, but it's not working

12:55 djork: he uses emacs and clojure-mode, no slime

12:56 ambient: duncanm hmm well i've never done that. if it were me i'd just add a function that writes some more stuff into the JTextArea.

12:56 i dont know what you're trying to do

12:56 drewr: djork: he uses emacs+clojure mode

12:57 whoops, didn't see duncanm's response

12:57 duncanm: ooh

12:57 djork: cool

12:57 drewr: promise!

12:57 djork: (glad there's so many rhickey fans in here):)

12:58 drewr: while we like rhickey, we're not so much fans of him as his work (which I think he prefers)

12:59 rys: I'm a big fan of his hair

12:59 But mostly Clojure

12:59 arsatiki: it must be nice to have a name like his, because then you never feel poor

13:01 djork: indeed

13:05 Kjellski: Hi there =)

13:09 djork: Kjellski: howdy

13:09 how's the learning going?

13:09 I have been playing with your bacteria problem

13:10 without great success, I might add

13:10 notallama: i don't think i could easily go back to no slime.

13:11 Kjellski: ... still problems with recur... but I´m trying hard... got time to look at a snipped``

13:11 ?

13:11 It´s not that easy right?

13:11 djork: sure

13:11 :)

13:13 Kjellski: http://paste.lisp.org/display/89304

13:13 =)

13:14 My problem is, that the populate should be called with an initially population and an initial day... like (populate [1] 1) ... but it will never stop... blowing the jvm...

13:14 djork: yeah

13:14 Kjellski: nevermind the doalls in that other function ^^

13:16 djork: heh

13:16 Kjellski: C´mon, tell me...

13:21 falkor: Hi, Here is a silly question from a newbie: How can I execute a LazySeq (ie, make it a IFn)?

13:22 Kjellski: You mean, get all values out?

13:22 That would be a (doall lazy-seq)

13:22 falkor: let me try...

13:23 Kjellski: But be carefull with infinite definitions... ^^ they last long...

13:28 qed: im having some trouble understanding iteration in clojure

13:28 i see these combinations of loop, recur, inc, dec, iterate, etc.

13:29 djork_: oops

13:29 qed: how do i make the basic example of two nested for loops

13:29 djork_: Kjellski: out of memory on 100th day

13:30 Kjellski: djork : damned ^^ got something running that´s not working... and we need some not stack consuming construction with letfn or so!?

13:31 djork_: something like that

13:31 proper tail-recursion would do the trick

13:31 although I ran out of heap not stack

13:31 Kjellski: Just combine, like (for [a b] (for [c a] ... )) ?

13:31 @ qed

13:32 djork_: Kjellski: I think he means nested for loops in another language

13:33 like two Java for loops

13:33 qed: im trying to decrement from 999, and increment from 901

13:33 djork_: in Clojure for creates a seq

13:33 and it also binds multiple seqs to iterate over

13:33 ,(doc for)

13:33 clojurebot: "([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr ...], :while test, :when test.

13:33 qed: it's one of the euler problems where i need to try combinations of multiplying 3 digit numbers

13:33 The-Kenny: qed: Show an example in some pseudocode.

13:35 djork_: ,([x (range 1 10) y (reverse (range 1 10))] [x y])

13:35 clojurebot: java.lang.Exception: Unable to resolve symbol: x in this context

13:35 djork_: oops

13:35 ,(for [x (range 1 10) y (reverse (range 1 10))] [x y])

13:35 clojurebot: ([1 9] [1 8] [1 7] [1 6] [1 5] [1 4] [1 3] [1 2] [1 1] [2 9] [2 8] [2 7] [2 6] [2 5] [2 4] [2 3] [2 2] [2 1] [3 9] [3 8] [3 7] [3 6] [3 5] [3 4] [3 3] [3 2] [3 1] [4 9] [4 8] [4 7] [4 6] [4 5] [4 4] [4 3] [4 2] [4 1] [5 9] [5 8] [5 7] [5 6] [5 5] [5 4] [5 3] [5 2] [5 1] [6 9] [6 8] [6 7] [6 6] [6 5] [6 4] [6 3] [6 2] [6 1] [7 9] [7 8] [7 7] [7 6] [7 5] [7 4] [7 3] [7 2] [7 1] [8 9] [8 8] [8 7] [8 6] [8 5] [8 4] [8 3] [8 2

13:35 ambient: is there any performance difference between (let [foo 1 bar 2] ...) and (let [foo 1] (let [bar 2] ...)) ?

13:35 djork_: sorry, too many for an example :)

13:36 ,(for [x (range 1 3) y (reverse (range 1 3))] [x y])

13:36 clojurebot: ([1 2] [1 1] [2 2] [2 1])

13:36 qed: (loop (for n=999; n < 901; n-- (for k=901; k<=999; k++ ( test-if-this-is-palindrome(n*k)))))

13:36 i know i dont need that loop, but id like to use special forms instead of for loops

13:36 like fn/loop/recur

13:36 The-Kenny: qed: I think for is the thing you need.

13:36 chouser: ambient: I think those produce the same bytecode

13:37 ambient: chouser thanks

13:37 qed: so it will multiply 999*901, 998*902, 997*903, etc.

13:38 Kjellski: maybe this works for you? (for [n (reverse (range 901 999)) k (range 901 999)] (test-palin (* n k)))

13:39 qed: Kjellski: where do you close the [

13:39 before the k?

13:40 oh nevermind

13:40 Kjellski: ;9

13:40 qed: im getting used to this whole [] thing

13:40 you are defining sequences within []

13:40 Kjellski: if you need, you could also place some commas in there, they are interpreted just like spaces...

13:40 That´s it!

13:41 chouser: ,(loop [i 5, v []] (if (zero? i) v (recur (dec i) (loop [j 5, v v] (if (zero? j) v (recur (dec j) (conj v [i j])))))))

13:41 clojurebot: [[5 5] [5 4] [5 3] [5 2] [5 1] [4 5] [4 4] [4 3] [4 2] [4 1] [3 5] [3 4] [3 3] [3 2] [3 1] [2 5] [2 4] [2 3] [2 2] [2 1] [1 5] [1 4] [1 3] [1 2] [1 1]]

13:41 qed: so could i also do: (for [n (range 901 999)] (for [k (999 901)] (test-valid n*k)))

13:41 The-Kenny: I think he could also use the :when keyword

13:42 chouser: but you rarely need such nastiness. use 'for' if it'll do for you.

13:42 Kjellski: With a range in the k thing?

13:42 falkor4: argh.... network problems

13:42 djork: for + range = bliss, honestly

13:42 I see no need to do it recursively

13:42 falkor4: Sorry, I just lost track of the previous conversation

13:43 Does anyone has any idea on how to execute a LazySeq?

13:43 Kjellski: ,(doc doall)

13:43 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

13:43 djork: falkor4: you can use doall doseq, etc

13:43 there's another one that doesn't retain the head

13:44 dorun

13:44 ,(doc dorun)

13:44 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

13:44 djork: (testing...)

13:44 ~dorun

13:44 clojurebot: Pardon?

13:45 qed: how do i only print (* n k) when reverse-and-test is true?

13:45 right now this loop tests those combinations, but just prints a ton of falses for me

13:45 The-Kenny: qed: Add a :when and the predicate afterwards to the binding-list

13:46 (I was trying to suggest this, but emacs doesn't let me copy the text...

13:46 Kjellski: The-Kenny : /agree

13:46 The-Kenny: qed: Like (for [a (range) b (range2) :when #(is-prime? (* %1 %2))] (* a b))

13:47 qed: why the lambda?

13:47 The-Kenny: Because my fictional is-prime? takes one argument

13:47 and for passes both arguments to the fn

13:48 somnium: you can also use a let binding before when

13:48 it makes it more readable sometimes

13:48 falkor4: As an example, if I do (let [x (concat '(println) '(1))] (doall x))

13:48 I get nothing

13:48 somnium: :let [z (* x y)] :when #(is-prime? z)

13:49 qed: somnium: this is inside the for loop?

13:49 somnium: yup

13:49 qed: in the binding of the foor loop

13:49 The-Kenny: Wow, I didn't know :let is supported there. Cool :)

13:49 qed: for loop

13:49 ok

13:49 somnium: clojure's list comprehensions are amazing

13:49 destructuring everywhere to boot

13:49 The-Kenny: qed: The last thing will only get executed if the predicate after :when is true.

13:50 (Forgive me... my english isn't very good ;))

13:52 qed: okay i think i got this working

13:52 now the only thing left is, i get it to print all trues, how do i get it to print the output from * n k, when it's true

13:52 more :when code?

13:52 The-Kenny: qed: Show what you have now.

13:52 somnium: ,(doc complement)

13:52 clojurebot: "([f]); Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value."

13:52 The-Kenny: qed: For returns a list. You could just print this sequence.

13:53 qed: (for [n (reverse (range 100 999))

13:53 oops, let me pastie this

13:57 http://pastie.org/private/tfgbeacofcqgfxk8rowiq

13:58 ^^That's what I have so far

13:58 it prints every instance where reverse-and-test is true

13:58 The-Kenny: qed: Just remove the reverse-and-test just before the last )

13:58 (Just (* a b) in the body)

13:59 The last part of the for will get executed for each element where the :when-predicate returns true and the result of the call is added to a list

13:59 qed: how does apply work?

14:00 like (apply max (for...))

14:00 ,doc apply

14:00 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/doc

14:00 hiredman: ~def apply

14:00 The-Kenny: Apply takes a fn and a list and will apply the elements of a list to the fn.

14:00 (apply max [1 2 3 4 5 6]) == (max 1 2 3 4 5 6)

14:00 hiredman: nice

14:00 nginx 404

14:01 qed: So what does my for loop return to us then? a seq?

14:01 The-Kenny: Yes

14:01 Kjellski: jap

14:01 The-Kenny: Of the palindromes, if your predicate is correct

14:01 qed: clojure.lang.LazySeq

14:02 hiredman: ~for

14:02 clojurebot: for is not a loop

14:02 qed: yayyy i got the answer!

14:02 thanks for your help

14:02 hiredman: ~botsnack

14:02 clojurebot: thanks; that was delicious. (nom nom nom)

14:02 qed: lol

14:02 i think those noms would give us more happiness if they were capitalized


14:02 Kjellski: Are you solcing challenges?

14:03 qed: Kjellski: yeah

14:03 Kjellski: On hacker.org?

14:03 qed: project-euler.net

14:03 Kjellski: =) !Have fun! (=

14:03 spuz: qed: I thought I recognised that problem :)

14:03 qed: Originally I had this really bright idea to just find what 999*999 was, and then descend from there, testing each result decrementing down for a palindrome

14:04 unfortunately the palindrome i find doing that, is not able to be composed by multiplying 2, 3 digit integers

14:04 so i had to brute force :(

14:05 spuz: qed: you can improve it a bit by only testing for each pair of numbers once

14:05 The-Kenny: memoize! :)

14:05 Kjellski: djork: Got something running, also with attention to memory, but it´s just not spitting the right answer for 8 days ...

14:05 spuz: at the moment you have n = 100-999, k = 100-999, you could have n = 100-999, k = n-999

14:06 qed: once i bind n in my for loop, and i use it immediately within the same binding?

14:06 spuz: yep :)

14:06 qed: like [n (range 100 150) k (range n 200)]

14:06 if i define n in terms of itself will it blow up?

14:06 :)

14:07 hiredman: n is not a number there

14:07 n is range

14:07 and range takes numbers, not ranges

14:07 qed: "Elapsed time: 2679.445 msecs"

14:08 (the old way)

14:08 "Elapsed time: 1347.57 msecs"

14:08 spuz: hiredman: I'm pretty sure my solution uses exactly that construct

14:08 qed: (spuz's way)

14:08 spuz: thanks for that tip

14:08 spuz: and apparently it works for qed :)

14:08 hiredman: ah, I see

14:08 (for ...)

14:08 spuz: yeah, it's not a let :p

14:09 The-Kenny: A tribute to geocities: http://xkcd.com/642/ :)

14:12 qed: so quick question

14:13 Kjellski: Damned... just not getting it.

14:13 qed: how does :when work there, it says "when" to add (* n k) to the new seq?

14:14 Kjellski: It´s just executing the body, ":when" the condition is true...

14:15 djork: http://paste.lisp.org/display/89310

14:16 qed: Kjellski: thanks again man!

14:16 Kjellski: qed: welcome...

14:17 qed: you know, normally somebody is helping me... so this is the least =)

14:18 qed: haha, well eventually ill be able to offer something back to the newcomers, but im struggling to keep my head above water right now

14:18 some of it seems to make perfect sense, but then other things, that seem like they should be so easy, look so different

14:18 let bindings and all of that are very new to me

14:18 anyway gotta get back to work, lunch is over

14:18 ciao

14:18 Kjellski: For me too, and then, for me it´s also my first lisp... ^^

14:18 vya

14:18 bye

14:19 qed: Kjellski: same here, first lisp

14:33 scottj: how do I change a struct-map into a normal map so I can dissoc?

14:33 chouser: (into {} m)

14:36 scottj: sorry, my stupid irssi was messed up and I didn't see that. did you just answer my q?

14:42 piccolino: Is there some way in Slime to make the current expression get sent to the REPL? That is, so that it appears in your REPL buffer, and not in your minibuffer?

14:42 (This is with Aquamacs and Clojure).

14:42 Kjellski: Maybe C-M-X or does it affect your buffer?

14:43 err C-M-x

14:43 chouser: scottj: use 'into' to convert just about anything to a clojure persistent datastructure

14:43 scottj: like (into { } other-map)

14:43 piccolino: Kjellski when I do that command, it tells me the result in the minibuffer (eg, "nil"), but then the function is not defined when I switch to the REPL.

14:44 Kjellski: piccolino: it is, if it is a function... but a call will give you the result...

14:44 piccolino: Hm, nope.

14:45 Not in "inferior lisp" or "Slime-repl clojure."

14:45 Kjellski: Okay, sorry... I´m using ClojureBox so maybe it´s something else here...

14:45 Are you sure you´re doing it on a (defn ... ?

14:45 piccolino: Yup.

14:46 Kjellski: Forget everything I said. Sorry.

14:46 piccolino: Oh, how embarrassing.

14:46 duncanm: hmm

14:46 piccolino: I forgot to qualify the function with the namespace when I was in the repl.

14:46 duncanm: anyone familiar with Swing here?

14:47 piccolino: It does work, thanks Kjellski.

14:47 Kjellski: piccolino : welcome =)

14:48 ambient: anyone know how i can control in Emacs which buffer windows stay unchanged?

14:48 it annoys me greatly when a command like C-x C-b (list buffers) changes a random buffer window

14:49 i tried browsing emacs wiki but found nothing obvious solution to this

14:50 tomoj: ambient: if you find something ping me

14:51 maybe #emacs would be more helpful

14:51 piccolino: OK, next question: how can I make a repl use a namespace even though it can't find the file to load the namespace fun? So I don't have to type out everything with the full namespace?

14:52 ambient: (ns your.namespace) i'd think

14:52 at least has worked for me so far

14:52 djork: ,(doc import)

14:52 clojurebot: "([& import-symbols-or-lists]); import-list => (package-symbol class-name-symbols*) For each name in class-name-symbols, adds a mapping from name to the class named by package.name to the current namespace. Use :import in the ns macro in preference to calling this directly."

14:52 Kjellski: ,(doc use)

14:52 clojurebot: "([& args]); Like 'require, but also refers to each lib's namespace using clojure.core/refer. Use :use in the ns macro in preference to calling this directly. 'use accepts additional options in libspecs: :exclude, :only, :rename. The arguments and semantics for :exclude, :only, and :rename are the same as those documented for clojure.core/refer."

14:52 piccolino: I tried use, it complains it can't load the file.

14:53 tomoj: then you must load the file

14:53 hiredman: piccolino: well, then you can't use it

14:53 tomoj: or put it someplace so that clojure can find it

14:53 hiredman: you can just create the namespace

14:53 but it will be empty

14:53 tomoj: well you could just (load "/full/path/to/file.clj"), no?

14:54 djork: OK so about loading with use

14:54 if I have foo.clj

14:54 and . in my classpath

14:54 hiredman: djork: you already failed

14:54 piccolino: OK, "ns" worked, thanks ambient.

14:54 djork: oh

14:54 hiredman: ~namespace

14:54 clojurebot: Titim gan éirí ort.

14:54 hiredman: ~namespaces

14:54 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

14:54 djork: well ok then :)

14:54 tomoj: why is it that you can't use single segment namespaces?

14:55 hiredman: you can, they just don't behave well, so I discourage their use

14:55 tomoj: ah

14:55 Kjellski: djork: there you are... ^^

14:56 djork: hey

14:57 yeah I'm at work (doing non-Clojure 99% of the time)

14:57 trying to squeeze it in for server stuff

14:57 Kjellski: Urgh, sorry... ^^

14:57 Just go on ^^

14:57 djork: heh it's find I use fun languages anywa

14:57 Rails, ObjC

14:57 my typing is awful today

14:58 notallama: is objC a superset of c?

14:58 Kjellski: Better than mine, everyday.

15:00 The-Kenny: notallama: It's used in Osx. Things like classes, functors, message-passing etc. are the features.

15:01 djork: ObjC is fun. It's like Smalltalk bolted onto C.

15:01 [foo messageWithArgument:bar andAnotherArgument:baz];

15:01 lots of typing though

15:01 The-Kenny: heh, yeah.

15:02 duncanm: hmm

15:02 i don't think i can bind *out* in the swing EDT

15:02 notallama: that's always the way with c-like languages. they're verbose.

15:02 djork: [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[self context] sectionNameKeyPath:nil cacheName:nil];

15:03 :)

15:03 hiredman: duncanm: what do you mean?

15:03 The-Kenny: djork: don't forget to call release :)

15:04 duncanm: hiredman: i tried something like (SwingUtilities/invokeLater #(... (binding [*out* out-writer] ....))), but in my click handler, println still goes to the normal stdout

15:04 Chousuke: the interleaved message send syntax is one of ObjC's good points though :P

15:04 duncanm: hiredman: but i use (.println System/out "foo"), then it goes to my swing window

15:05 hiredman: duncanm: pastebin some code?

15:05 duncanm: hiredman: sure

15:09 hiredman: http://clojure.pastebin.com/d15eaac29

15:10 hiredman: makes sense?

15:13 Chousuke: duncanm: I don't think the binding is in effect anymore after you've created the buttons.

15:13 duncanm: Chousuke: so what can i do?

15:16 Chousuke: duncanm: capture the value of *out* in a local when the click proxy is created and rebind it in the body

15:16 hiredman: pass out-stream around?

15:16 duncanm: eew, that's kinda lame

15:17 Chousuke: you can also change the root binding :P

15:17 hiredman: ~url

15:17 clojurebot: something

15:17 hiredman: lisppaste8: url

15:17 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

15:17 duncanm: why is it that *out* is not dependant on System.out?

15:17 hiredman: ah, i'll use that pastebot next time

15:18 lisppaste8: hiredman pasted "binding *out*" at http://paste.lisp.org/display/89315

15:18 Chousuke: duncanm: because System.out can't be rebound, I guess :P

15:18 hiredman: you can set System.out

15:18 duncanm: i did

15:18 Chousuke: yeah, but that's not what I meant.

15:18 duncanm: but it doesn't affect println

15:18 i suppose i can keep out-stream in the top-level

15:18 Chousuke: duncanm: the default root binding of *out* just happens to be System.out. that's all.

15:18 they're completely separate otherwise

15:18 duncanm: how do i change the root binding?

15:19 Chousuke: alter-var-root!

15:19 hiredman: :(

15:19 Chousuke: it's safe, and fine, too. as long as you do it only once...

15:19 duncanm: i can do it in my -main

15:19 Chousuke: if you build your logic around changing it and then setting it back, you should figure out some other method :)

15:19 duncanm: i'm not gonna set it back

15:20 Chousuke: should be okay, then.

15:21 but hm

15:21 why is your OutputStream proxy calling print?

15:21 won't that cause a loop?

15:21 duncanm: oh

15:21 print is a local fn

15:21 Chousuke: ah, yeah. shadows the global ;/

15:22 I don't like pastebin's syntax highlighting at all... too low contrast.

15:23 duncanm: (alter-var-root *out* #(out-writer)) ;; that doesn't work

15:24 notallama: there's a "!", i think.

15:24 Chousuke: it's an alter-style function

15:25 you'll want (fn [_] out-writer)

15:25 also you'll want (var *out)* instead of *out*

15:25 oops

15:26 djork: pastebin is pretty terrible :)

15:26 Chousuke: anyway, since it's an alter function, you're supposed to use it like (alter-var-root! #'*somevar* inc)

15:27 djork: (might I suggest http://gist.github.com/ for your paste needs)

15:28 Chousuke: gists are great

15:28 they actually *highlight* code instead of just colouring it :P

15:29 djork: yeah, seriously... I can *check out a paste*

15:30 Chousuke: heh

15:30 you can actually commit too

15:31 clojurebot started as a gist

15:31 hiredman: http://delicious.com/clojurebot/pastbin btw

15:31 Chousuke: full development history exists

15:31 duncanm: hmm

15:31 Chousuke: I just cloned it from the gist and pushed it on github at one point :P

15:32 hiredman: I was using bzr, and had a script that would copy clojurebot.clj to the git clone of the gist, and commit and push

15:32 :/

15:33 Chousuke: heh. do you use git nowadays, though? :P

15:33 hiredman: yes

15:33 Chousuke: good. :)

15:34 * technomancy is contributing to a bzr-based project. it beats svn, but I'll leave it at that.

15:34 djork: hah hah

15:34 Chousuke: vimperator moved onto hg at one point, and I actually tried to use hg

15:35 I found the lack of local branches disturbing.

15:35 djork: SVN is fine. It's like the Honda Civic of version control.

15:35 hiredman: my dotfiles are all still in bzr

15:35 Chousuke: I can use git as an SVN client, so SVN is passable.

15:35 technomancy: hg has local branching now

15:36 Chousuke: yeah, I tried some extension, but... It just isn't git ;/

15:37 git lets me do whatever I want with my branches and commits and I kind of like that :)

15:39 The hg worldview seems to be that commits and branches exist forever and are indestructible :/

15:39 Kjellski: Bye for today... cya

15:40 Chousuke: I guess I could have adapted hg to my workflow if I had put in more effort but I finally just ended up importing the hg repo into a git one :P

15:41 djork: git wins whenever there is any question about workflow

15:43 duncanm: is there a standard technique for processing argument lists that are in the form of a plist?

15:43 technomancy: duncanm: (apply hash-map args)

15:44 hiredman: :(

15:45 you could just use hash destructuring

15:45 duncanm: hiredman: yeah, what's the syntax for that?

15:45 hiredman: clojurebot: destructuring

15:45 clojurebot: destructuring is http://clojure.org/special_forms#let

15:45 * technomancy always forgets about hash destructuring

15:52 AWizzArd: it's very useful

15:52 i also ignored it several months

15:58 duncanm: sigh, doto doesn't work with set! and fields

16:01 djork: how do you mean

16:08 duncanm: djork: you can't write (doto x (set! foo 1)) to mean (set! (.foo x) 1)

16:09 somnium: how can you get to clojure metadata from .java?

16:09 duncanm: oh wait

16:10 nah, you can't

16:11 djork: that doesn't make sense

16:12 duncanm: it'd be nice to have (doto x (set! .foo 1))

16:19 tomoj: hmm?

16:19 somnium: you can get to clojure metadata from java

16:19 somnium: I know its possible, I didn't find the right incantation while looking

16:20 tomoj: just call .meta() on it

16:20 you will get an IPersistentMap back

16:20 somnium: ok, trying to find a way to avoid reflection in a proxy class, that should do it

16:20 tomoj: oh, I thought duncanm was talking to you

16:21 duncanm: what would that even mean?

16:22 oh, you mean assigning to a public field, I see

16:25 djork: slutty types...

16:25 rhickey: ok, bridge method generation in place for newnew/defclass*

16:25 djork: implement setFoo and (doto x (.setFoo 1)) and you're done

16:32 duncanm: djork: not when it's not my own class

16:32 Chousuke: duncanm: (-> x .foo (set! 1)) :/

16:32 djork: ew, who designed a class with important public fields... I need to know so I don't accidentally hire

16:33 chouser: rhickey: woohoo!

16:36 stuartsierra: chouser: what's woohoo?

16:38 cemerick: stuartsierra: "rhickey: ok, bridge method generation in place for newnew/defclass*"

16:38 rhickey is rebuilding the foundation while we party in the rafters :-)

16:39 stuartsierra: heh

16:39 At the rate he's going, he's going to have to call it Clojure 2.0 instead of 1.1.

16:40 technomancy: hehe

16:45 jasapp: somnium: thanks for congomongo

16:55 skillet-thief: trying to get slime working. I get into an *inferior-lisp* buffer with clojure,

16:55 but no slime buffer. Am i missing something obvious?

16:56 technomancy: skillet-thief: did you install via M-x clojure-install or manually?

16:56 somnium: jasapp: hows it working for you?

16:56 djork: skillet-thief: I'm going to guess that this is the second time you're starting Emacs after clojure-install.

16:56 skillet-thief: technomancy: manually

16:56 djork: oh, wrong

16:57 skillet-thief: clojure-install means going through elpa, right?

16:57 technomancy: skillet-thief: no, it performs git checkouts for you

16:57 it's orthogonal to elpa

17:00 skillet-thief: ok, I'm going to try again with clojure-install and come back later. Thanks!

17:02 djork: skillet-thief: just pay special attention to the post-install note

17:02 technomancy: djork: I learned my lesson; the next version will not require so much attention to detail to install. =)

17:02 djork: :)

17:03 it's not so baad

17:03 it's quite slick

17:03 it's just the note on the first line is easy to miss

17:03 technomancy: I do get a number of people who miss it though. I think I can do better.

17:03 somnium: I tried installing the latest but I couldn't figure where it put anything and wasn't in the mood to configure emacs :(

17:05 The-Kenny: My installation of swank-clojure is a bit fragile... I don't want to touch a file, it could destroy everything!

17:05 technomancy: just wait, the next version will be simpler.

17:05 as soon as I can get two hours to myself to finish it. (so maybe around mid-November)

17:05 somnium: heh

17:06 spuz: technomancy: next version of what?

17:06 technomancy: swank-clojure

17:07 djork: technomancy: yeah I'm a little fuzzy on where it goes

17:08 (too)

17:13 yuras: i want to build jsonrpc server using http as transport layer, and im not sure about choosing appropriate http lib for that. will jetty be okay? or should i go with something more simple like one of embedd into jdk http servers? im a bit newbie about java world, came from python :) please advise

17:13 hiredman: I wrote an extremely minimal http server for clojurebot

17:14 tomoj: so I think the best representation for my graphs is four maps, from node ids to seqs of outgoing edge ids, from node ids to seqs of incoding edge ids, from node ids to node data, and from edge ids to edge data

17:15 yuras: hiredman: thanks, will check out now... i just dont want to reinvent the wheel and follow idiomatic way of clojure.

17:15 tomoj: which is... weird

17:15 hiredman: http://github.com/hiredman/clojurebot/blob/master/hiredman/http_server.clj

17:15 tomoj: when I've used jetty with compojure it's been stupid simple

17:16 duncanm: is condt the right library to use to get a 'case' macro?

17:16 tomoj: I really don't know anything at all about jetty, and yet I've used it successfully

17:16 duncanm: i don't see it in clojure-contrib

17:16 chouser: duncanm: cond and condp are built in

17:16 yuras: tomoj: i know, but isnt to heavy for just simple jsonrpc lib, which is supposed to be easy reused...

17:16 duncanm: chouser: i want something that looks like case in Scheme

17:17 hiredman: http_server.clj and factoid_server.clj allow for json queries of clojurebot's factiods over http

17:18 yuras: hiredman: thank you very much, im almost there with your code

17:18 hiredman: http://www.thelastcitadel.com/lab/clojurebot.html <-- generated by querying clojurebot via json

17:18 rhickey: case-like switch thingy coming soon

17:18 duncanm: rhickey: oh? that's nice

17:19 stuartsierra: duncanm: condp (built-in) is very close to case; clojure.contrib.fcase is an alternative

17:19 rhickey: the case I'm doing will have constant-time dispatch

17:21 stuartsierra: Yeah, yeah, I'll constant-time dispatch YOU. :)

17:21 chouser: ,(condp get :beta, #{:foo :bar} "classic", #{:alpha :beta} "greek", "other")

17:21 clojurebot: "greek"

17:22 chouser: duncanm: that's *not* constant-time dispatch, but might be close to what you want

17:23 rhickey: Scheme case is not guaranteed constant time anyway

17:24 and yes, the condp example is a good equivalent

17:26 hiredman: I've been using (condp = …) a lot

17:33 duncanm: Chousuke, if I use (-> x .foo (set! 1)), what's the syntax for setting .bar?

17:33 i mean, .foo and .bar

17:33 Chousuke: hm, I guess you can't :/

17:33 duncanm: yeah

17:33 Chousuke: you need to make your own macro :)

17:33 duncanm: i'm always coming up with little syntactic things that i wanna change

17:33 Chousuke: well, you can :P

17:34 duncanm: last time, it was having automatic proxy-ication

17:34 but rhickey shot down that idea ;-/, oh well ;-P

17:34 Chousuke: it's almost trivial to make a (set-fields! x .foo 1 .bar 2 .zonk 3)

17:34 duncanm: right

17:35 i know syntax-rules and E-R macros from Scheme, but i haven't really looked into writing Clojure macros

17:35 Chousuke: you just return plain lists of symbols and such

17:35 usually using syntax-quote

17:36 eyeris: When I evaluate my file via vim-clojure, all of the defns succeed, but the code that actually does something doesn't seem to be run.

17:37 hiredman: duncanm: clojure macros are just functions that s-expressions and return s-expressions

17:37 duncanm: hiredman: sure, all lisp macros are like that ;-P

17:37 hiredman: i just need to sit down and learn it, that's all

17:37 eyeris: For example, at the bottom of the file, below the last defn, I can put (+ 1 2). I see the last defn is established, but it never evaluates (+ 1 2)

17:38 Chousuke: (defmacro set-fields! [object & fields] `(do ~@(map (fn [[field foo]] `(set! ~object ~(list field foo))) (partition 2 fields))) or something

17:38 though probably has problems with multiple evaluation

17:39 also I didn't count the closing parens :P

17:41 also it wouldn't work anyway.

17:41 hm

17:42 moral of the story: don't write macros in irssi ;(

17:42 chouser: heh

17:43 tomoj: eyeris: how do you know it never evaluates (+ 1 2)?

17:43 eyeris: tomoj It is never printed in the preview window.

17:44 tomoj: well, I dunno anything about vim-clojure, but I would be somewhat surprised if it DID print anything

17:44 maybe try (println (+ 1 2))?

17:44 eyeris: tomoj: Why?

17:44 maacl: All three Clojure Quicksorts at Rosetta Code (http://rosettacode.org/wiki/Quicksort#Clojure) are broken for large collections. How would one write one that works for large collections?

17:44 tomoj: does it print out the result of every single form in the file when you compile something?

17:44 that would be incredibly annoying to me

17:45 eyeris: You're missing the point tomoj. It's a repl. The println is implicit.

17:45 tomoj: it's not a repl if you're compiling a file...

17:45 rhickey: wanted - suggestions for alternative to 'expando' for talking about automatic extensible keys/assoc support for deftype/defclass

17:45 eyeris: I am not compiling a file.

17:46 chouser: maacl: broken in what way?

17:46 eyeris: rhickey: You just want a better name? Or a better implementation?

17:46 tomoj: so, what do you mean "evaluate my file"?

17:46 you're going form-by-form and sending those forms to the repl?

17:46 rhickey: eyeris: name :)

17:46 eyeris: tomoj: Nevermind man. This is a vimclojure thing. It works fine from the std repl, when compiling, etc.

17:46 chouser: aux-keys

17:46 maacl: chouser: they blow the stack - all use direct recursion

17:47 tomoj: does "evaluate a file" in vimclojure mean "send every form in the file to the repl and print its result"? just curious, feel free to ignore me :)

17:47 eyeris: tomoj: Yes, that's precisely what it means.

17:47 tomoj: wow

17:48 why is that useful?

17:48 eyeris: tomoj: It's useful so that you don't have to startup your program every time you make a tiny change.

17:49 tomoj: I must be confused

17:49 I don't ever have to do that and I don't have that feature

17:50 oh well

17:50 eyeris: tomoj: do you use emacs?

17:50 tomoj: indeed

17:51 duncanm: oen thing that always bugged me about clojure is that the functions are read top-down, so I have to always order my functions carefully - is there something i can do so i don't have to do that?

17:51 tomoj: (doc declare)

17:51 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

17:51 duncanm: tomoj: so i have to declare everything ahead of time?

17:52 tomoj: I think maybe doing otherwise has unpleasant consequences?

17:52 eyeris: tomoj: I think the emacs/slime equivilent is C-c C-l

17:52 tomoj: maybe it breaks the conflation of compile-time/eval-time or something?

17:52 eyeris: ok, but C-c C-l doesn't print out the result of each and every form in the file

17:52 eyeris: I'm not sure though. I've never felt comfortable in emacs.

17:53 tomoj: that's the puzzling part to me

17:53 djork: maacl: they need to be made tail-recursive and use the recur facilities

17:53 eyeris: tomoj: M-x slime-eval-buffer?

17:53 djork: I'm still too much of a n00b to do it myself.

17:54 AWizzArd: rhickey: "inject", "inject-keys"

17:54 tomoj: eyeris: that prints out the result of only the last form in the file

17:54 maacl: djork: yeah I figured as much, but can really see how to do it since they all need to recur on both parts of the list

17:54 tomoj: which, if it's something like (+ 1 2), is 3, yes

17:55 djork: yeah, I don't really know the best way to do it

17:55 above my head

17:55 tomoj: eyeris: what does it print out when the last thing in the file is a def(n)?

17:55 something like "#'foo"?

17:55 eyeris: #'edu.wisc.uwsc.xlsmerge.gui/build-main-window

17:55 maacl: djork: same here

17:55 tomoj: yeah, then that is pretty odd

17:56 have you tried putting something that takes a really long time?

17:56 as in, maybe it's evaluating it but just not printing it for some reason?

17:56 eyeris: When it works, it's very quick.

17:56 AWizzArd: rhickey: "introduce", "extend", "grow", "enlarge"

17:57 chouser: rhickey: we're looking for a noun, right?

17:57 eyeris: I think it has something to do with the repl server not being able to create a Swing frame, but I don't know because I can't get an error out of it.

17:58 tomoj: what do swing frames have to do with (+ 1 2)?

17:59 eyeris: tomoj: (+ 1 2) evals properly when it is before the defns but not after the defns

17:59 All of the defns are involved with Swing GUI construction

17:59 tomoj: and you're actually calling one of those functions somewhere up there?

18:00 eyeris: Nope

18:00 tomoj: doesn't make sense that they would hang, then

18:00 to me, anyway

18:00 until they're called

18:01 somnium: what's the most straight-forward .java way to create a PersistentHashMap?

18:01 rhickey: chouser: something like :meta, for metadata

18:02 chouser: I like :aux

18:03 :extra :bonus :supplementary

18:04 AWizzArd: bonus sounds funny :-)

18:04 Chousuke: somnium: RT.map()?

18:04 eyeris: quit

18:04 rhickey: I wonder how fine grained it should be, could just be based on interfaces

18:04 (defclass name [fields] #^{:disable #{Seqable Associative}} [interfaces] & methods)

18:05 AWizzArd: Can the granularity be configurable?

18:05 rhickey: basically there will be several auto-implementd interfaces you need to be able to turn off

18:05 AWizzArd: what does that mean?

18:06 hrm, interfaces list not a good place for that, since it might not be present. (deftype [a b c]) perfectly ok

18:07 AWizzArd: you said it could just be based on interfaces.. what would be the alternative?

18:07 rhickey: oops (deftype Foo [a b c]) perfectly ok

18:08 AWizzArd: :meta toggles IObj/IMeta, :expando-whatever toggles Associative+

18:08 Chousuke: so wait, you have both deftype and defclass?

18:08 rhickey: Chousuke: yes, deftype is a dynamically typed thing (think more powerful structs), defclass is a regular named class

18:09 Chousuke: ah, okay.

18:11 rhickey: could also be toggled by presence of explicit methods, but that's tricky since only some might be implemented, overlap between interfaces etc

18:11 also, methods not required

18:11 Chousuke: that sounds like too much magic :/

18:12 rhickey: someone might want a very simple non-extensible struct-like thing without meta/lookup/extension at all

18:22 AWizzArd: Chousuke: :aux or :aux-keys is good

18:23 rhickey: yes, exactly such a struct with clojure syntax is what we need

18:42 steiger: Chousuke, rhickey , what is this deftype/defclass about? does it have something to do to contrib's deftype?

18:42 hiredman: ~datatypes

18:42 clojurebot: http://www.assembla.com/wiki/show/clojure/Datatypes

18:43 hiredman: I think those notes are already obr

18:53 defn: I need to find the 10001st prime. Anyone have any good lazy prime sieve code?

18:54 ls

18:57 hiredman: clojurebot: sieve?

18:57 clojurebot: Excuse me?

18:57 hiredman: clojurebot: the genuine sieve of eratosthenes

18:57 clojurebot: the genuine sieve of eratosthenes is http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

18:58 hiredman: clojurebot: sieve is <reply>see the genuine sieve of eratosthenes

18:58 clojurebot: Ok.

18:58 LauJensen: hiredman, check out cgrands blogpost re the same

18:59 hiredman: LauJensen: hey, I kicked my euler habit, so I am not interested in lazy infinite sequences of primes

18:59 LauJensen: k

19:00 defn: heh

19:00 it's a bad habit isnt it

19:01 cgrands post is old though, it uses lazy-cons

19:06 somnium: hmm, how would I go about calling the JSON parser in contrib from java?

19:06 hiredman: you get a hold of the var

19:07 so you need a symbol

19:07 somnium: import clojure.lang.Symbol ?

19:07 god I forgot how much I hate java

19:07 hiredman: Var.find(Symbol.create("some.namespace.qualified.symbol"))

19:07 then you need to deref the var

19:07 v.deref()

19:08 so you should have an IFn

19:08 fn.invoke(arg1, arg1, ...)

19:08 somnium: cool

19:08 I may make this mutable spaghetti speak a little clojure yet

19:09 any ideas on what kind of object would make a good proxy between struct maps on the one side, and mutable hash-map derivatives with string keywords on the other?

19:10 hiredman: ~def c.l.LispReader

19:10 technomancy: what's the converse of nth?

19:11 converse may not be the exact right word, but given an item and a collection, what's the position of that item?

19:11 somnium: it needs to be mutable for all nasty side effecty functions called on it by the java api, serialize clojure to json, and return IPersistentMaps to clojure

19:11 offset?

19:13 hiredman: (get (nth (map vector coll (iterate inc 0)) n) 1)

19:13 well

19:13 technomancy: I thought it was added to clojure core

19:13 hiredman: hmmm

19:13 technomancy: or possibly somewhere in contrib, though I'm not finding it in seq-utils

19:14 defn: how do i convert a massive biginteger, into a sequence of integers

19:14 hiredman: defn: #euler or something

19:14 somnium: :)

19:15 defn: treat it like a sequence of integers of course

19:17 steiger: OH

19:17 i was struggling with how to represent some adts (too much choices, no default one)

19:18 i'm glad to see the plans to datatypes

19:18 *plants to new datatype features

19:27 timothypratley: I have some sort of classpath problem but not sure how to resolve it:

19:28 user=> (compile 'sandpit.button)

19:28 java.io.IOException: No such file or directory (button.clj:3)

19:28 (ns sandpit.button

19:28 (:gen-class))

19:28 It is finding button.clj to compile it, but then when not happy with the ns declaration

19:29 And I can't see any reason why

19:51 Oh hmmm nevermind, no classes directory caused it.

21:03 hircus_: if I use struct-map to create a new map, is there a way to check which "interface" it implements?

21:03 or is it wholly duck-typed?

21:07 tomoj: hircus_: I was wondering that a couple days ago

21:07 it seems the reference to the structmap object is private

21:07 so afaik no way to get at it

21:08 if you have a reason to care about that sort of thing you should probably put a :type field in the metadata

21:08 hircus_: tomoj: ah, that's a bummer. true, that'd bloat the size a bit though

21:08 tomoj: (with the help of a make-foo function or such perhaps)

21:08 well, hmm

21:08 hircus_: I guess I could gensym the type to make sure it is unique (but that'd make it non-serializable)

21:09 probably ok in this context, actually

21:09 tomoj: if you have (def foo [bar] (with-meta bar {:type 'foo}))

21:09 when you call foo on two different objects, are their metadata maps identical?

21:10 nope, they aren't

21:11 that seems kinda strange to me, I would've expected the map that gets put into the metadata to be the map the reader read, which would be the same always

21:11 somnium: hircus_: what do you mean what interface?

21:12 tomoj: my completions on the slime repl suddenly don't work

21:12 somnium: hircus_: struct definition or interface as in IPersistentMap

21:13 hmm, anyone know where a definitive guide to gen class is?

21:13 hircus_: tomoj: they are identical when I tried it

21:13 somnium: found almost contradictory versions on two wikis

21:13 hircus_: tomoj: user> (= (meta (foo x)) (meta (foo y)))

21:13 true

21:13 somnium: struct definition

21:13 tomoj: = is not identical?

21:13 hircus_: tomoj: ah, yes. == returns false

21:14 tomoj: well, that's because they're not numbers

21:14 you're looking for identical?

21:14 hircus_: aha

21:14 somnium: why not use a macro to add the meta data automagically?

21:14 hircus_: so I can use identical? if I want to be anal, and have a private map

21:14 tomoj: so that means every time you make a structmap with your {:type 'foo} metadata you have to allocate that map

21:14 hircus_: somnium: I'm going to do that, I'm just looking for a form that is small enough

21:14 tomoj: somnium: why a macro and not a function?

21:14 somnium: better performance would be one argument

21:15 tomoj: I wonder if they'd be identical, then

21:15 somnium: but I don't know, you could certainly use a function

21:15 functions always have to be called, and defstruct involves def so a macro seems appropriate

21:15 tomoj: yeah

21:17 still not identical, but in this case it makes perfect sense to me why they're not

21:19 somnium: I compiled my gen-class in slime, and no errors, but it couldn't the .class file. So I build it with ant and it blew up right away

21:20 tomoj: aha

21:20 somnium: and I can't even find a confirmation of the right syntax

21:20 tomoj: (def foo ((fn [meta-map] (fn [bar] (with-meta bar meta-map))) {:type 'foo}))

21:20 I wonder if there's an easier way to do that

21:20 somnium: you could comp them for less overhead

21:21 no nevermind, youre return a fn, I'm tried

21:21 tomoj: of course this is almost certainly pointless except as an exercise :

21:21 somnium: think of the fun it would be to implement that with anonymous class ;)

21:22 tomoj: but,

21:22 ,(let [foo ((fn [meta-map] (fn [bar] (with-meta bar meta-map))) {:type 'foo})] (identical? ^(foo []) ^(foo {})))

21:22 clojurebot: true

21:39 eyeris: The /api page doens't render properly in FF 3 (neither normal mode nor safe mode) for me. Does it work for anyone else?

21:39 tomoj: yep

21:39 but a couple others have complained of the same problem

21:39 timothypratley: mostly :)

21:39 eyeris: tomoj what version do you have?

21:39 tomoj: well, if the problem is that it cuts off half way through or something

21:40 ambient: it's a firefox bug. sometimes the bottom of the page (or all of it) are black for long lists or pages of text

21:40 eyeris: Right, that's the problem I am having.

21:40 I have 3.5.3

21:40 tomoj: I dunno my firefox version right now - only have conkeror here

21:40 will check in a bit

21:40 ambient: usually it works

21:40 eyeris: ambient: It never works for me on the /api page.

21:40 tomoj: sometimes it causes a bug in conkeror too, strangely

21:40 but not a rendering bug

21:41 ambient: 3.5.3 also

21:41 works fine atm

22:03 manby-ace: is there a way to get a list of the methods that a java object implements from clojure?

22:04 tomoj: (require '[clojure.contrib.repl-utils :as repl])

22:04 (repl/show the-java-object)

22:04 that's for looking for your own convenience

22:04 for getting a list you can work with programmatically I guess you'd use java reflection or something

22:06 manby-ace: tomoj: thanks very much, that's exactly what I need - just for the repl.

22:07 tomoj: if you're using slime there's a fancier way, too

22:08 though, now when I try it it doesn't show methods, only fields

22:10 manby-ace: cheers - I am - will investigate further

22:11 arohner: is anyone using a graph / charting library in webapps?

22:11 I need something that will print a graph (like graphviz) to a web page, and haven't found anything good yet

22:12 jasapp: incanter?

22:12 arohner: incanter is more of a statistics library, and it uses jfreechart to draw

22:12 AFAIK, jfreechart doesn't have anything for showing a graph / tree

22:14 Flox_: arohner: JGraph is LGPL since a few weeks: http://www.jgraph.com

22:16 arohner: Flox_: interesting, thanks

22:16 Flox_: arohner: sorry - missed the bit about "web apps". JGraph also have a JS lib called mxgraph, but it is not free.

22:16 arohner: Flox_: can it serve a png?

22:18 Flox_: arohner: I would guess so, but I haven't used it lately (just about 10 years ago, when it was not completely free...)

22:19 arohner: Flox_: thanks anyways

22:28 Flox_: About the Firefox / API page rendering problem: It works if you disable some CSS scripts via the "Web Developer" extension. Alas, I do not yet know exactly which style (combination) causes the effect.

22:30 ambient: the bugs appears only like 5% of the time, and usually when i dont have time to debug :)

22:32 Flox_: arohner: I might soon need to serve some graphs too, so I'd be keen to learn what worked for you! Good luck!

22:32 Good night all!

22:42 djork: is there any logic to choosing a namespace?

22:42 Licenser: somnium: what clojure version do you need for your mongodb driver?

22:43 somnium: Licenser: Ive been using recent 1.1

22:43 didn't test against 1.0

22:43 Licenser: ah that explains :)

22:43 somnium: is it broken?

22:43 Licenser: yes

22:43 because clojure/walk does not seem to be there

22:43 somnium: I have a 1.0, will it not build at all?

22:43 really

22:43 well, it won't be needed shortly

22:43 tomoj: djork: java standard is to start with reverse domain name

22:43 djork: well yeah

22:44 but what if I don't have a domain name

22:44 tomoj: dunno

22:44 somnium: was talking with eliot at mongo today, and almost have a .java proxy class

22:44 Licenser: somnium: nice!

22:44 tomoj: if your project has a unique enough name it's not so bad to just use it, I guess

22:44 compojure does this for example

22:44 somnium: he hacked in an interesting hook, that didn't quite work, but he set me on the right track (I hope)

22:44 its a bit of a compromise

22:44 Licenser: ^^

22:45 somnium: its a mutable thing that can take keywords and handle json

22:45 but its definitely not clojure, mutable like jelly :)

22:45 * Licenser waits for the oblegory stoning for mentioning mutable

22:45 Licenser: ^^

22:46 somnium: it will be performant, most db transactions won't alter records, if youre doing number crunching just cast them I guess

22:46 (shrug)

22:46 Licenser: :)

22:47 hmm when I build a jarfire for a clojure project, it won't automatically include all the needed clojure framework files right?

22:49 somnium: it depends on the build.xml

22:49 I try to keep them slim, you could end up with five clojure jars in your lib dir if youre not careful

22:50 he got it so you can put keywords in as values, but that's kind of useless

22:51 clojure.walk is sloooow, got to get rid of it, good for macros but not running thousands of little hashmaps

22:51 Licenser: ^^

22:51 somnium: I want to get it work first of all, I don't yet worry about slow or fast

22:52 somnium: all the tests passed before I pushed, I swear

22:52 will put a note about 1.1 I guess, but I only think two people besides me have tried it so far :)

22:53 Licenser: wooh so I'm the second beta tester :P

22:53 erm alpha tester

22:53 somnium: pre-alpha tester :)

22:54 Licenser: omega tester?

22:55 somnium: gamma at least

22:57 Licenser: heh

22:57 still breaking narf

22:57 I guess I also need the mongodb java driver?

23:00 hrm, it's really not easy to get your driver to work somnium :P

23:00 java.lang.ClassNotFoundException: clojure.core$_EQ___4369 <- not good

23:00 I guess

23:00 djork: n00b question: what's the best way to set up a "main" entry point for a clojure project

23:01 somnium: yeah

23:01 but, its in deps

23:01 Licenser: for me it's 4341 in the end

23:01 odd very very odd

23:01 somnium: Licenser: hmm, you have bleeding edge clojure jar somewhere?

23:01 Licenser: yes I just downloaded and ant'ed it from github

23:02 that is what I'm using

23:02 somnium: git clone .... cd congomongo... ant -Dclojure.jar=path/to/that/clojure.jar

23:02 Licenser: but seriousely i know that isn't a congomongo problem, how the hell did that happen?

23:02 Flox_: arohner: I just read up on JGraph: The license is now BSD (used to be LGPL for the renderer and proprietary for the layouter, which is now included - see http://www.jgraph.com/forum/viewtopic.php?f=13&t=4472). PNG / headless seems possible (http://www.jgraph.com/pub/jgraphmanual.pdf, pp. 95ff.)

23:02 somnium: hrmm

23:03 what error are you getting?

23:03 Licenser: class not found: java.lang.ClassNotFoundException: clojure.core$_EQ___4369

23:03 he does not found EQ

23:03 oddly enough my cloure package implements only clojure.core$_EQ___4341

23:03 somnium: ...

23:04 yikes,

23:04 Licenser: yes I find that very very odd

23:04 but with recompiling it works

23:04 somnium: let me push my clojure jar and see if that works for you

23:04 it worked?

23:04 Licenser: yes

23:04 somnium: sweet

23:04 Licenser: but I wonder, does that mean I've to have the exact smae clojure jar to make other people's jar work?

23:04 that would be a very new definition of unportable :P

23:04 somnium: well, I guess edge isnt very stable

23:05 clojure's been moving fast though, always new toys

23:05 Licenser: but EQ isn't that new

23:05 somnium: maybe its an AOT thing? no idea, I can barely read java anymore

23:05 http://pastie.org/671153

23:06 look at this crap, just to get a function out of contrib to use in java

23:06 Licenser: heh

23:06 Java sucks, but java sucked before clojure existed :P

23:07 somnium: true, but I wouldn't be writing java now if it weren't for clojure :/

23:07 Licenser: teehee

23:12 the one thing that realy makes me cry with clojure are the horribly bad exceptions

23:13 it's as bad as java just a bit worst since you've a gazillion lines of stacktrace :/

23:14 very helpful texts like: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.NullPointerException

23:22 hmm I see another problem but it seems to be a mongodb prolem

23:23 no it's not

23:23 somnium: why is the driver casting integers to floats? :P

23:23 that is a bugy bug

23:32 somnium: ?

23:33 what produced it?

23:35 tomoj: if I pass an array of Objects to a java method which is overloaded to accept both Object and Object[], is it possible the Object one is called?

23:35 somnium: Licenser: did you run the tests?

23:35 tomoj: is type-hinting the way to solve this?

23:36 Licenser: somnium: if I fetch from my collection he gets float backs and nope, no clue how to o.O

23:37 somnium: same as build, just add test at the end

23:37 plenty of integers not getting cast over here, can you past what produced the bug?

23:37 Licenser: ahh sneaky

23:40 somnium: all passed

23:40 tomoj: to answer my own question, yes

23:40 Licenser: tomoj: glad we could help *hides*

23:40 tomoj: :)

23:41 I was getting a very strange error on a pretty much direct port from working java

23:42 because, I guess, clojure can't tell that when you pass an Object[] in, it shouldn't call the method that takes an Object

23:42 somnium: wtf is up with java exceptions, why won't they just let world end to see what breaks?

23:42 tomoj: in my case that's exactly what they did :)

23:43 hiredman: ,(ancestors (class (to-array [])))

23:43 clojurebot: #{java.io.Serializable java.lang.Object java.lang.Cloneable :clojure.contrib.generic/any}

23:43 Licenser: somnium: java exeptions were introduced to toss the russions of the track back in the cold war, sadly the scientist who came up with that plan commited suicide shortly after when he tried to compile some java code and only got cryptic expetions

23:43 somnium: this attempt at java has driven me back to netbeans

23:44 tomoj: huh

23:44 how did that :clojure.contrib.generic/any get there

23:44 hiredman: ,(doc derive)

23:44 clojurebot: "([tag parent] [h tag parent]); Establishes a parent/child relationship between parent and tag. Parent must be a namespace-qualified symbol or keyword and child can be either a namespace-qualified symbol or keyword or a class. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to, and modifies, the global hierarchy."

23:45 tomoj: oh, I see

23:45 I always figured ancestors just meant superclasses/interfaces

23:45 hiredman: ,(doc supers)

23:45 clojurebot: "([class]); Returns the immediate and indirect superclasses and interfaces of c, if any"

23:45 tomoj: :)

23:45 somnium: hiredman: I was able to get to contrib.JSON with your help, but I can't figure out what exception to throw and where to put return on the invoke :(

23:46 hiredman: I finally knocked me reader back into shape

23:46 somnium: ,(isa? String "foo")

23:46 clojurebot: false

23:46 hiredman: somnium: Exception

23:46 somnium: I love that

23:46 hiredman: return on the invoke?

23:46 oh

23:46 somnium: yeah

23:46 hiredman: invoke returns an Object

23:46 somnium: hmm

23:47 hiredman: so you have to cast it to whatever

23:47 IPersistantMap or something

23:47 somnium: #$%^ ... java

23:47 I just need a string

23:47 20 locs to call one function and return a string

23:47 hiredman: so you are generating json?

23:48 somnium: yeah, I need to override mongo's json parser

23:48 djork: ,(class "foo")

23:48 clojurebot: java.lang.String

23:48 djork: wait...

23:48 tomoj: ,(ancestors "foo")

23:48 clojurebot: nil

23:48 tomoj: huh?

23:48 somnium: (class (class "foo"))

23:48 ,(class (class "foo"))

23:48 clojurebot: java.lang.Class

23:48 hiredman: ,(ancestors (class "foo"))

23:48 clojurebot: #{java.io.Serializable java.lang.Object java.lang.Comparable java.lang.CharSequence :clojure.contrib.generic/any}

23:48 djork: ,(isa? String (String. "foo"))

23:48 clojurebot: false

23:48 djork: HAH

23:48 hiredman: ,(isa? String (class "foo"))

23:48 clojurebot: true

23:49 hiredman: ,(doc isa?)

23:49 clojurebot: "([child parent] [h child parent]); Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy"

23:49 tomoj: oh, it's for classes, yes, of course :)

23:49 Licenser: ,(isa? String (new String "a"))

23:49 somnium: the docs for isa? and derive were seriously designed to confuse in my opinion

23:49 clojurebot: false

23:49 somnium: (instance? String "foo")

23:49 djork: so "derived" does not mean the instance but the class

23:49 hiredman: there is no type inheritance relationship between the java class String and the String instance "foo"

23:49 somnium: ,(instance? String "foo")

23:49 clojurebot: true

23:49 djork: ok there we go

23:49 Licenser: ,(doc isa?)

23:49 clojurebot: "([child parent] [h child parent]); Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy"

23:49 hiredman: it doesn't say "derived"

23:50 it says "derive"

23:50 somnium: hiredman: I understand that only because I understand it

23:50 hiredman: which is a specific function

23:50 somnium: not because it was even remotely intuitive or obvious

23:50 Licenser: I find that very confusing

23:50 somnium: its a bit like emacs

23:50 hiredman: *shrug*

23:50 djork: oh well, now I know the difference between isa? and instance?

23:51 Licenser: isa? does not what you expect, instance? does

23:52 hiredman: http://en.wikipedia.org/wiki/Is-a

23:52 it's a technical term

23:53 Licenser: I still didn't expected that :p

23:53 somnium: http://pastie.org/671207 <- ok I'm an idiot, what do I need to make this compile? its the last line of code

23:53 hiredman: if you know the term, you do

23:54 you need to return a string in the catch

23:54 somnium: of course

23:55 hiredman: I've been reading and re-reading java a lot lately

23:55 somnium: its odd that the compiler would find 'println "The world ended."' so satisfying

23:55 hiredman: and doing some IFn invoking from java

23:55 I finally sorted out a big tangle in my reader

23:56 somnium: I really want to be using gen-class but I can't find any comprehensive examples

23:56 hiredman: really?

23:56 somnium: well, I followed to, and the first one was broken, and then I got frustrated and decided to finish this java file

23:56 djork: Clojure - because it's still faster than Ruby

23:57 somnium: hiredman: if you could point to any real usage in the wild or examples I would love it

Logging service provided by n01se.net