#clojure log - Dec 18 2009

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

0:20 scottj_: Am I missing something or does clojureql not have an equivalent of limit?

0:21 polypus: does the order of definition of defmethods have any effect on dispatch?

0:28 alexyk: how do you compare strings?

0:30 ,(< "a" "b")

0:30 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number

0:30 kylesmith: ,(.compareTo "a" "b")

0:30 clojurebot: -1

0:31 alexyk: thx!

0:32 where does compareTo come from?

0:32 ah, ok .

0:33 chouser: polypus: no, I don't think so.

0:33 polypus: if there's any ambiguity, it must be resolved with 'prefer'

0:34 alexyk: I compare pairs of form [string vector], by longer vectors first, then ties broken by alphabetic order of strings. This works but is ugly: (sort (fn [[k1 v1][k2 v2]] (let [len1 (count v1) len2 (count v2)] (if (> len1 len2) true (if (< len1 len2) false (.compareTo k1 k2))))) coll) ; ways to improve?

0:34 polypus: chouser: ty

0:38 chouser: alexyk: did you try a default sort?

0:39 alexyk: chouser: it does the opposite: by keys and small lengths

0:39 chouser: ah

0:39 alexyk: I'd reverse it. but then alphabetic order is broken

0:39 chouser: yes

0:43 maybe (sort (fn [[k1 v1][k2 v2]] (let [len1 (count v1) len2 (count v2) c1 (compare len1 len2)] (if (zero? c1) (compare k1 k2) c1))) coll)

0:43 hardly better though, if it even works

0:43 alexyk: chouser: cutier

0:46 chouser: (sort-by (fn [[k v]] [(- (count v)) k]) coll) ?

0:48 polypus: ,(doc prefer)

0:48 clojurebot: I don't understand.

0:48 chouser: ,(doc prefers)

0:48 clojurebot: "([multifn]); Given a multimethod, returns a map of preferred value -> set of other values"

0:48 chouser: ,(doc prefer-method)

0:48 clojurebot: "([multifn dispatch-val-x dispatch-val-y]); Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y when there is a conflict"

0:48 chouser: there it is. sorry.

0:49 alexyk: you saw that sort-by?

0:49 biab

0:49 alexyk: hah

0:49 polypus: no worries. i was wondering about the conflict bit. are you explicitly told by clojure aout conflicts?

0:50 s/aout/about

0:50 alexyk: interesting -- will try after re-vectoring seconds, they were seqs and it takes forever for counts to get retaken every time

0:58 defn: how do you use 1.1.0 with technomancy's swank?

1:10 scottj_: defn: copy it to ~/.swank-clojure/clojure-1.0.0.jar I think

1:11 defn: wish there was a way to choose

1:11 or a var to set

1:36 chouser: polypus: yes, Clojure will complain when a multimethod is called if the dispatch result is ambiguous.

1:48 alexyk: is ArraySeq usually counted?

1:50 I did (->> ... (frequencies) (sort) as the second component above, and it takes forever to sort with my comparator above taking (count <of that>). Should I have added ... (vector)?

1:51 Without (vector), the type is ArraySeq; with (vector), it's PersistentVector. On both toy examples say counted? => true. I wonder what happens when they come from lazy data.

1:51 I have 3.5 million pairs with those seconds, and it takes more than an hour already to sort.

2:06 polypus: chouser: ty

3:07 defn: is freenode still acting weird?

3:40 triyo: I see there is a bean function, is there a to-bean function of some sort that does the opposite?

4:01 LauJensen1: triyo: Did you look in contrib, there's a jmx module I think

4:02 http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/jmx.clj

4:03 triyo: LauJensen1: hmm, that mbeans. :)

4:04 LauJensen1: oh, sorry

4:04 triyo: no wrorries

5:45 octe: i was looking at http://github.com/richhickey/clojure/blob/1.1.x/changes.txt but i don't see anythign about defmulti.. didn't the signature for it change?

5:45 between 1.0 and 1.1

6:07 triyo: I'm confused, when is the right time/place to use the "do" form?

6:12 fanatico: when you're calling a function for its side effect, and want to return a different value.

6:13 Raynes: triyo: In places like an if expression, where you want to call functions for side effects, but want to return a different value than the one those functions return.

6:15 triyo: for example like this snippet: http://gist.github.com/259443 its nothing but full of side-effects... should there be a do there

6:15 Raynes: ,(if false 3 (do (+ 2 2) (* 3 3) 5)) ; Useless example.

6:15 clojurebot: 5

6:16 triyo: Raynes: if expression is the only place where I do know how to use it and where it makes sense

6:16 Raynes: If I don't /have/ to use it, I don't.

6:17 triyo: Raynes: for example, would you use it in my snippet gist above?

6:18 around the doto all way to the end

6:18 Raynes: Nope.

6:19 triyo: ok, thats the same feeling I had.. just trying to make sure I don't use it unnecessarily.

8:25 fliebel: Why doesn't Clojure have objects?

8:26 fogus: It has objects all over the place ;)

8:28 fliebel: like?

8:29 fogus: Do you mind rephrasing the question? Do you mean to ask why it's not object-oriented?

8:29 fliebel: You mean because every seq is in fact a java class?

8:29 yea, that is more or less what I mean

8:31 I understand it's not good from the functional immutable point of view, but I guess it would make java interop a lot easier.

8:33 karmazilla: dot-syntax is simple, calls into java are wrapper free, and it's easy to implement interfaces with proxy

8:33 fogus: RH has talked about this in many places, so I probably would not do him justice in paraphrasing. However, the basic point is that traditional OO is not conducive to concurrent programming.

8:34 fliebel: What do you see as the hard points on interop?

8:36 fliebel: fogus: Nothing specific… It's just that for me it's a pain to work with those java libraries. And since Clojure has almost no stdlib on its own, for almost any non trivial task you would have to do some java stuff…

8:39 fogus: fliebel: Without knowing your problem-space it's tough to know how interop is failing you, but I do not agree that interop is required outside of toy problems. There are countless examples of very tough problems solved by Clojure core libs alone.

8:41 fliebel: for example, this simple command: Runtime.getRuntime().exec("ls") translates into (.exec (java.lang.Runtime/getRuntime) "ls") and then I still have to find out how to create a reader to get the output…

8:42 fogus: fliebel: Maybe I'm being dense, but I'm not sure how Clojure being OO helps in this case

8:43 fliebel: fogus: not in this case, but then I never tried to write a Clojure applet…

8:43 karmazilla: fliebel: there's shell-out in contrib

8:44 fogus: What he said ^^^^^^

8:45 fliebel: karmazilla: I know...

8:46 chouser: I think Clojure not being object *oriented* is more about the idiomatic way to solve problems than it is about the lack of any particular feature.

8:47 fliebel: Okay, it might be a bad idea to go oo, but I do think java interop is a pain, at least for me it is.

8:49 karmazilla: "Runtime.getRuntime().exec("ls")" is more about Java inter-operating with C, isn't it?

8:51 so it's more like Java being a pain (and this pain leaking through in Clojure) than Java interop per se.

8:53 fliebel: karmazilla: that might be part of the problem...

8:57 but why can't it be like ((java.lang.Runtime.getRuntime) exec "ls"), or whatever… just some more java-ish(without changing order and thinking about dot vs slash.)

9:01 fogus: fliebel: Clojure as a Lisp follows the prefix notation -- in the case of interop that function position is a method. It's a uniform syntax

9:04 Raynes: Clojure isn't supposed to be 'javaish'.

9:04 It's quite a bit Clojureish.

9:17 murbank: Do chunked sequences make expressions no longer strictly lazy? So (take 5 (expensive-io-function-returning-seq)) might make more expensive io evaluations than strictly necessary?

9:25 chouser: murbank: possibly, but it's generally controlled by the seq-generator.

9:25 so if expensive-io-function-returning-seq knows it is expensive and laziness is important, it can simple return a non-chunked seq and all is well.

9:48 murbank: chouser: Are new "primitive" sequences chunked by default?

9:49 chouser: murbank: only a few are so far. seqs of vectors being the most notable. also 'range'

9:51 murbank: chouser: But the intention is that many more are to be added right?

9:51 chouser: I'm not sure. I wouldn't expect line-seq to go chuncked, for example. But I don't know of any specific plans one way or another.

10:14 fliebel: What is the correct way to send off some function for which I don't care about the return value? I guess it's something like an atom, agent, ref, whatever, but I don't really understand those.

10:22 chouser: fliebel: perhaps 'future'

10:23 rhickey: yes, future, just ignore its return

10:25 fliebel: thanks

10:36 * stuartsierra is testing out 1.1-RC1

10:36 rhickey: yay

10:36 stuartsierra: readme typo: missing colon after "To Run"

10:39 chouser: also in readme, under Futures "They are away" should be "a way"

10:39 stuartsierra: chouser: you mean changes.txt, right?

10:40 chouser: er. right.

10:41 stuartsierra: rhickey: mind if I fix up the formatting in changes.txt? Stuff like breaking lines at 70 characters.

10:42 rhickey: stuartsierra: no, go ahead, thanks

10:42 stuartsierra: ok

10:48 rhickey: stuartsierra: could you also add that add-watcher and remove-watcher are gone, but can be implemented in terms of add-watch and remove-watch?

10:48 stuartsierra: rhickey: sure

10:48 rhickey: thanks

10:49 chouser: Repl and Script are missing from Deprecated

10:51 stuartsierra: chouser: ok, will mention that too

11:07 Can I associate a commit with multiple tickets?

11:11 chouser: I think so. Just list them all in the commit msg

11:11 stuartsierra: ok

11:12 rhickey: done, #229 ready to test

11:55 efarrar: hello

11:55 rhickey: stuartsierra: your patch file seems to include some of my patches

11:56 stuartsierra: oh, drat, I patched from master, didn't I

11:56 rhickey: ah, yup

11:56 stuartsierra: ok, trying again...

11:56 rhickey: I've touched 1.1.x, so make sure you have the latest

11:57 stuartsierra: got ti

11:57 got it

11:58 rhickey: ok, new patch up

12:04 rhickey: stuartsierra: applied and pushed - thanks!

12:04 stuartsierra: You're welcome!

12:41 cemerick: stuartsierra: I must be missing something about the complexity of integrating JUnit <-> clojure.test. Isn't it just a matter of generating one JUnit testcase that straps up clojure.test?

12:43 stuartsierra: cemerick: If you only want a single pass/fail for all your Clojure tests, yes.

12:44 cemerick: oh, you're aiming for full correspondence in the resulting report

12:45 stuartsierra: Otherwise, what's the point?

12:46 cemerick: well, the OP in that thread was just looking to have the clojure tests invoked as part of the default test run. I didn't think proper correspondence was an objective.

12:46 stuartsierra: I suppose so.

12:46 chouser: I'm useing clojure.test inside a junit suite in clojure

12:47 stuartsierra: chouser: how?

12:47 chouser: top-level java file for the annotation stuff

12:48 then a macro that does gen-class for one junit test per clojue.test fn

12:48 stuartsierra: Ah, I see.

12:48 chouser: the reports aren't terribly pretty

12:48 I've been hoping to look at the new junit stuff for clojure.test

12:48 stuartsierra: It's in 1.1; haven't played with it much myself.

12:48 cemerick: I guess I have really low expectations for test reporting. :-)

12:49 jasapp: does anyone know if there is anything like CL's hyperspec-lookup for clojure?

12:49 the-kenny: jasapp: (doc fun)

12:50 stuartsierra: Not quite the same.

12:50 There's a javadoc lookup function in contrib.

12:51 jasapp: I have the javadoc lookup, and it's nice

12:51 I was just looking for something similar for clojure

12:51 stuartsierra: (doc f) gets you the same thing as the Clojure API docs, except for special forms.

12:51 clojurebot: Excuse me?

12:52 jasapp: ok

12:52 I'm not sure why I didn't think of that

12:52 replaca: jasapp: find-doc also exists

12:52 when you don't know the exact form

12:52 cemerick: this is interesting: http://code.google.com/p/terrastore/

12:52 replaca: *symbol name

12:53 * the-kenny just had a really cool idea: Extending swank-clojure to show the arguments in java-interop too

12:53 replaca: rhickey: are you in channel?

12:54 rhickey: replaca: yup

12:55 replaca: rhickey: so I was thinking that since autodoc doesn't support branches yet, I could do a stopgap by putting the 1.1 doc up on tomfaulhaber.github.com/clojure and then we'd have poor man's branch support

12:55 how's that sound?

12:56 (not that master and 1.1 have diverged yet) :)

12:58 rhickey: replaca: the API doc was always advertised as being about the latest, I'm ok with that until we have branch support

12:59 we can work on putting metadata for :introduced-in for 1.2+

12:59 hiredman_: I thought the api was always advertised as being about the release

13:00 replaca: rhickey: ok, cool. I'll relax about that then. I think I'm about a month away from branch support (I'm doing some cleanup and trying to turn autodoc into a library that others can use right now)

13:00 hiredman_: I'm not sure we made any declaration at all :)

13:00 chouser: replaca: I noticed that the namespace is in both the path and the fragment of the doc urls

13:01 rhickey: the clojure.org API page always said latest

13:01 replaca: chouser: I don't understand what you mean?

13:01 hiredman_: ok

13:01 replaca: chouser: oh, yeah I do. Yeah, that's probably unnecessary

13:02 "for historical reasons"

13:02 :-0

13:02 :)

13:04 rhickey: I should probably add some words to the top of the API page emphasizing that this documents the master branch

13:06 rhickey: used to say: "It is generated from the source and reflects the current SVN version."

13:06 replaca: I'll add similar verbiage for the moment

13:14 rowth: llastlog changes

13:14 gah, sorry

13:19 replaca: rhickey: how about :introduced-in and :modified-in so that we can reflect APIs that have changed reasonably (:modified-in could be a vector)

13:21 rhickey: replaca: they sound fine, if somewhat verbose

13:22 replaca: rhickey: yeah, I have no strong opinion on the names. whatever feels easiest to you when working on core.clj

13:41 bagucode: technomancy: ping

13:55 StartsWithK: gen-class will lift all constructors from the base class, is this feature of any use to any one?

13:56 hiredman_: lift?

13:56 StartsWithK: copy contructor signatures to gen-classed class

13:56 technomancy: bagucode: pong

13:57 StartsWithK: i was doing a sketch for joint java-clojure compiler (like the one groovy has) so first step is to generate .java stubs for all gen-class classes

13:57 then i would compile java side with them, remove stubs and recompile clojure part

13:58 this way in the same compile module you can have java side using clojure generated classes and clojure depending on java side

13:59 the problem is constructor lifting, i can't generate the stub if the base is still in .java file

13:59 hiredman_: hmmm

13:59 StartsWithK: at least i can't generate correct constructors

13:59 bagucode: technomancy: hey. I just sent you a bunch of github noob messages :) I'm curious about some common practices and stuff.

14:00 technomancy: bagucode: this is a pretty good overview of how I like to keep feature work in a separate branch until it's ready: http://wiki.github.com/dchelimsky/rspec/topic-branches

14:01 hiredman_: gen-class in generally is kind of distasteful, I'm not sure why it does the lifting, must be something to do with the init stuff on the clojure side

14:01 StartsWithK: so, maybe lifting could be removed in favore of explicit constructor declaration

14:01 joint java -clojure compiler imho is bether option to have

14:01 technomancy: bagucode: thanks for the patches; I hope to have time to look at them soon.

14:03 StartsWithK: yes, and i think there were several reports of gen-classes class not working, it happened i think when lifted constructor clashed with custom declaration or something like that

14:05 chouser: Aren't the ctors are lifted so you can dynamically add functionality?

14:05 bagucode: technomancy: Thanks. I'll read up on that link. My master now is just the first change I did to compile.clj to support native code. I didn't want to touch that again until you had a look at it and maybe merged it to leiningen proper so I made a new branch for the generic os detection support and passing of jvm flags to a forked process. Guess I got that right then :)

14:06 chouser: StartsWithK: like :init and :post-init

14:06 technomancy: bagucode: sounds like a winner.

14:06 StartsWithK: chouser: i don't know why is it doing it, but, couldn't you have same effect with manual lifting

14:06 stuartsierra: Yes, the gen-class'd constructor needs to call init, set up state, etc.

14:07 StartsWithK: hmm

14:08 but still, :constructor could be made explicit and mandatory in all cases

14:08 stuartsierra: That would be a nuisance.

14:08 StartsWithK: for what?

14:08 stuartsierra: Me. ;)

14:08 StartsWithK: i't looks like most gen-class is used to generate beans or similar things for servlets and such

14:09 and they need default ctor to work

14:10 if one could simply drop bunch of java scala and clojure file in same src/ dir and just complile them without any extra work on his part

14:10 that would be a huge benefit for ide makers

14:11 stuartsierra: Not gonna happen any time soon.

14:11 StartsWithK: groovy can do that, and they now have joint java/scala/groovy compiler, scala has joint java/scala compiler

14:11 only thing stoping clojure from this is ctor lifting

14:12 stuartsierra: Do they generate stub .java source? That's the part that sounds weird to me.

14:12 StartsWithK: stuartsierra: goovy generates stubs, scala generates bytecode

14:12 r*

14:12 my java/clojure compiler works like groovy implementation

14:13 its a three stage compilation, but is fully automatic and transparent for the user

14:13 hiredman_: I think the real issue is that clojure's compiler is same world and loads all the code it generates

14:14 stuartsierra: Yes, so you always have to compile Java code first.

14:14 StartsWithK: hiredman_: not a problem realy, only thing needed is to load .clj manualy, macroexpand while counting gen-class and gen-interface (deftype in new branc) as special forms

14:14 then collect bodies of gen-class declarations

14:15 hiredman_: StartsWithK: well then do that

14:15 if it is such a not a problem

14:15 stuartsierra: But gen-class is a function - it can be called anywhere, any time.

14:15 StartsWithK: stuartsierra: yes, java must be compiled first

14:15 its a macro, and it will not do anything if *compile-files* is not true

14:16 stuartsierra: But how can you do macroexpansion without evaluating code?

14:17 chouser: we have a dependency chain like this java -> clojure -> java -> C++

14:17 is that what you're looking for?

14:17 StartsWithK: i can't, but i don't need to do much, most thing are simple ignored (like (new Foo) will never be called)

14:18 chouser: something like that, but lets saj Foo.java will use Bar that is gen-classed, and Baz.java will use Bar, and you have them in the same lib

14:18 hiredman_: if clojure's compiler did not try to load java classes it would be possible to compile clojure first

14:19 StartsWithK: joint compiler will resolve that without any problems

14:19 stuartsierra: But what you're proposing is not really a joint compiler, just running separate compilers in a particular order.

14:19 StartsWithK: well that is what joint compiler does

14:20 stuartsierra: I think a joint compiler would have to understand both Java and Clojure syntax, so it can resolve symbols in both languages.

14:20 StartsWithK: hiredman_: it can work, no code will be executed, only evaluated, but the problem is, you can't know ctor of a class that is not compiled jet, so stub can't be generated

14:21 not realy, it only needs to provide all the classes from both laguages when they are doing there compile phase

14:22 (in compiled form or as stubs)

14:22 chouser: wait, you're trying to make gen-class work on a class that doesn't exist yet?

14:22 I mean, extending a class that doesn't exist yet

14:22 StartsWithK: yes, yes

14:22 chouser: the ctor is the least of your problems.

14:22 StartsWithK: it will be compiled by the java compiler

14:23 ctor is my only problem :)

14:23 chouser: gen-class generates a method for every public method of every class it's extending

14:24 StartsWithK: uff

14:25 with the same signature as the base?

14:26 then that is not the problem i think

14:26 as all publics from base would be visible any way

14:26 but ctors would not be lifted

14:26 chouser: not if base doesn't exist

14:27 how do you discover the public methods of a non-existant class?

14:27 conversly, why is the solution we're already using insufficient such that all this effort is required?

14:27 StartsWithK: i don't, but i dont care, it must be in class path, on it must be in javac stage compiled with other classes

14:28 i only need to generate stub "public Foo extend Bar .." as a string and save it in .java file for javac consumation

14:28 class*

14:35 this is http://is.gd/5sFXc explanation of hov groovy will do it, process is simple and it works on clojure if stub that is generated dosn't lift any ctors from the base class when :constructors in not defined

14:36 chouser: if you have each module declare its dependencies, then there is no problem at all, things just get built in the right order.

14:36 stuartsierra: Mixed-language projects are hard enough *without* cyclical dependencies.

14:36 StartsWithK: sure, if you want to place Foo.java in one module bar.clj in another and Baz.java in third and do manula dependency resolvig that way

14:37 headius: http://weblogs.java.net/blog/forax/archive/2009/12/18/tailcall-anyone

14:38 StartsWithK: stuartsierra: yes, so maybe it could get easier with things like this

14:38 headius: should take you guys about 5 minutes to toss the extra bytecode in

14:38 stuarthalloway: groovy: undisputed champ for those who like cross-language cyclical dependencies :-)

14:39 StartsWithK: circular dependency can't be resolved in any language, so it will fail as usual

14:39 joint compiler is not a wizzard

14:40 technomancy: headius: yow! what are the chances of that getting mainlined?

14:40 headius: I feel like there's a good chance

14:40 chouser: headius: how many -to-JVM-bytecode compilers do you have your fingers in?

14:40 headius: given the pushback to late 2010

14:40 technomancy: talking with John Rose at JRubyconf made me think odds weren't good, but that seemed to be only due to a lack of manpower. if the code's there and working...

14:40 headius: chouser: um...three or four of my own making, is that what you mean?

14:40 technomancy: exactly

14:41 chouser: headius: heh. yeah.

14:41 headius: it wouldn't just be useful for FP either...we could eliminate pure overhead" stack frames from our call stacks with it

14:41 StartsWithK: stuarthalloway: scala suports joint java/scala compilation too

14:41 headius: reflection could emit wide opcodes to remove themselves from backtraces

15:03 somnium: is there a particular function/method to call that coverts '? to _QMARK_

15:05 hiredman_: somnium: it's in the compiler

15:05 chouser: ,(clojure.lang.Compiler/munge "true?")

15:05 clojurebot: "true_QMARK_"

15:05 somnium: munge!

15:05 awesome, thanks

15:05 hiredman_: what does the "wide" bytecode instruction do?

15:05 stuartsierra: The most important function after "foo".

15:14 hiredman_: clojurebot: unix?

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

15:14 hiredman_: clojurebot: unix is<reply>it's a UNIX system! I know this!

15:15 clojurebot: unix is <reply>it's a UNIX system! I know this!

15:15 clojurebot: Ik begrijp

15:15 This is a test.

15:16 scellus: ,(sort [5 4 3 2 1 Float/NaN 1 2 3 4 5])

15:16 clojurebot: (1 2 3 4 5 NaN 1 2 3 4 5)

15:17 scellus: (not totally unheard of, python is similar)

15:19 doublindirection: how does clojure handle uncaught exceptions? they do not seem to "bubble up" to the repl

15:19 hiredman_: I really don't understand Compiler.java

15:20 chouser: doublindirection: I think they do bubble up to the repl. what are you seeing?

15:20 hiredman_: doublindirection: it depends on the context

15:20 threads/agents/etc

15:21 doublindirection: nothing unless I add a (try catch) and printing it

15:21 but it is happening in a thread ...

15:21 the-kenny: doublindirection: Exceptions aren't thrown across threads

15:21 They pop up in the *inferior lisp* buffer if you use swank-clojure

15:22 Exceptions in the repl-thread pop up in the repl

15:22 hiredman_: ,(future (throw (Exception.)))

15:22 clojurebot: #<core$future_call$reify__7719@1f87b38: :pending>

15:22 hiredman_:

15:22 the-kenny: ,(throw (Exception.)

15:22 clojurebot: EOF while reading

15:22 the-kenny: ,(throw (Exception.))

15:22 clojurebot: java.lang.Exception

15:22 doublindirection: i looked in *the inferior lisp*, nothing there

15:23 but it has to do with the threading

15:23 chouser: right, exceptions aren't printed by default except in a repl thread.

15:24 so if you start your own thread and throw something there, you won't find out about it automatically.

15:24 depending on how you start the thread, clojure may have some handy ways for you to find out about the exception.

15:25 the-kenny: chouser: Huh? Exceptions thrown in some thread pop up in my *inferior lisp*

15:25 doublindirection: the thread is a jms onMessage handler, who knows what happens

15:26 chouser: the-kenny: I don't use emacs. But if you do (def x (future (throw (Exception.)))) you see that exception?

15:26 the-kenny: chouser: wait

15:27 doublindirection: exception does not show in my emacs

15:27 the-kenny: chouser: No, but (.start (Thread. #(throw (Exception.))) pops up in *inferior lisp*

15:27 Maybe futures are handled differently?

15:28 chouser: the-kenny: hm, I guess you're right.

15:30 hiredman_: you can set an exception handler for threads

15:30 possibly the execturor future uses sets one

15:34 Licenser_: aloa

15:38 jweiss: i am looking for some macro examples that might help me - i write test automation software which requires me to support lots of different versions of our product. so my code (java) inevitably has lots of subclasses and overrides. i imagine the (a?) clojure way to do this is just patch the code with a macro? is there another way?

15:39 stuartsierra: jweiss: Dynamic binding.

15:42 jweiss: stuartsierra: what about the case in java where i just want to override one line of a method, so i abstract it out into a protected method and override that method?

15:43 defn: doug mcillroy patented macros

15:43 he also could set file permissions with a magnet and a pin

15:45 stuartsierra: same thing, just override a function with a different binding

15:46 jweiss: stuartsierra: i was hoping not to have to give these functions names. since they wouldn't be their own function if it wasn't for the needing to override it

15:47 hiredman_: defn: asm macros maybe

15:47 cp2: defn: what a noob, real programmers use C-x M-c M-butterfly

15:47 jweiss: was thinking of a form like (deprecated x y z) where x y z are the things i'm changing

15:47 or maybe deprecated is not the right name, but you get the idea

15:47 the-kenny: cp2: Hah... I love to hang out with people who understand this joke :D

15:48 cp2: ^_^

15:48 stuartsierra: jweiss: Well, you can't really change something unless you can refer to it...

15:49 jweiss: stuartsierra: yeah i meant i'd mark it my enclosing it in another form, and then a macro could replace the form with a new one

15:49 s/my/by/

15:49 stuartsierra: got to go

15:50 jweiss: k

15:52 defn: cp2: hehe check out: http://www.cs.dartmouth.edu/~sinclair/doug/

15:52 Doug McIlroy can address 8 terabytes of RAM with only 32 bits

15:53 and RE: ASM macros: Doug McIlroy thinks asm is for sissies.

15:54 the-kenny: Emacs can save files where bits have three states: 0, 1 and something between.

15:57 cp2: hehe defn

16:00 Licenser__: has someone has made any experience with clojure and sockets?

16:01 alexyk: chouser: you da man

16:02 KirinDave_: Licenser__: Like, raw sockets or just network stuff?

16:02 alexyk: the sort-by of the pairs finished in 300 secs, while sort with comparator in 5500 secs

16:02 Licenser__: KirinDave_: 'just network stuff' so to say :P

16:02 jweiss: ,(doc source)

16:02 clojurebot: "clojure.contrib.repl-utils/source;[[n]]; Prints the source code for the given symbol, if it can find it. This requires that the symbol resolve to a Var defined in a namespace for which the .clj is in the classpath. Example: (source filter)"

16:02 KirinDave_: Licenser__: The Peepcode is fairly good.

16:03 alexyk: apparently sort-by calls its by only once per element, effectively performing Schwarzian transform?

16:03 KirinDave_: Licenser__: Also, I wrote an example bit of code that's smaller. Let me get the link for you.

16:03 Licenser__: KirinDave_: there is one about clojure & network?

16:03 All examples I found were so simple and trivialized that they were kind of useless or even wrongisch

16:03 hiredman_: http://github.com/hiredman/clojurebot/blob/master/hiredman/http_server.clj

16:03 KirinDave_: Licenser__: The peepcode stuff uses duck-streams to write a simple MUD.

16:03 hiredman_: server socket

16:04 Licenser__: hiredman_: yes it is pretty cool but the client part isn't :P

16:04 KirinDave_: Licenser__: http://kirindave.tumblr.com/post/272596413/clojure-chat-server-1

16:04 hiredman_: Licenser__: huh?

16:04 chouser: alexyk: I'm surprised it was that much faster.

16:05 Licenser__: well I find it at times very unnice to read from the socket, I've had the problem that line-seq's on a socket keep spitting out nil's and prevent the socket from closing

16:05 chouser: alexyk: sort-by *could* do a Schwarzian transform, but looking at it's definition I don't think it currently does.

16:05 hiredman_: Licenser__: well they would

16:06 Licenser__: yea I found that ugly .P

16:06 hiredman_: anyway, http_server has only serversocket, no client stuff

16:06 alexyk: chouser: I also used it to sort by a function of the vector, and it was still very fast, hence I thought it only computes the by once, vs sort which apparently evaluates it for every comparison. But it's all speculation.

16:06 hiredman_: which is why I said "huh?"

16:06 Licenser__: I had so much fin defining a network connection by reducing over the seq of lines it spits out - I found it beautiful but it didn't worked as I wanted .P

16:07 hiredman_: well, you are computer programmer, make it do what you want

16:07 Licenser__: hiredman_: it's my plan :P just I learned that in clojure realms there are a lot people that have more experience so I see if someone knows tons of more stuff then me - especially when it gets all javaish like sockets :P

16:08 it helps against triplicated code but if most peopel played with server sockets I'll just make something nice to work with the reading part ^^

16:08 alexyk: I have a general question: so far, I keep all my clojure code as repl snippets, with def vars all around, reflecting a data mining session. Now if I want to place it into a maven dir structure and e.g. compile, it tries to eval each top level thing. Which is silly. How can I refactor things to (a) still allow easy copy-paste into repl in the same way (b) keep lein compile or mvn compile's dirty little hands off my def's?

16:09 Licenser__: alexyk: create a mdef macro that does nothing when in marvin and works as def if not?

16:10 hiredman_: alexyk: that is what def is

16:10 somnium`: Licenser__: marvin?

16:10 Licenser__: I like the robot!

16:10 somnium`: :-)

16:10 hiredman_: if you want to def something, and not have the code run until you call it, that is called a "function"

16:10 there is a special "defn" form for that

16:11 chouser: alexyk: it's not silly, it's optimization. You're doing all your computation at compile time, saving the end-user from having to do any at all!

16:11 alexyk: ah, somnium! Q for you: I hate java.util.Date, can there be a flag in congomongo to convert all dates to joda-time upon receipt from mongo-java?

16:11 hiredman_: chouser: nah, he will do it at compile time and at runtime

16:12 somnium`: alexyk: yeah, but you have to kind of hack on the driver

16:12 chouser: hiredman_: oh. I guess you're right. :-/

16:12 alexyk: hiredman_: so if I replace a def by a defn, i.e. creating a parameterless fun, will it run as (fenvar) ?

16:12 (funvar) I meant, kind of

16:13 hiredman_: alexyk: have you gone all this time without writing functions?

16:13 somnium`: alexyk: i.e, proxy a Transformer and fire it into bytes

16:13 alexyk: hiredman_: a few, but I rarely need them so far

16:13 hiredman_: well start writing

16:13 somnium`: alexyk: actually, could probably wrap it in a macro to make it stupid simple

16:13 alexyk: hiredman_: the question is, I have a series of interactive computations I check.

16:13 I need to see and refer to them by names.

16:14 hiredman_: write a function to check them

16:14 alexyk: think R.

16:14 somnium`: alexyk: Ill look into it

16:14 alexyk: it's a statistics session...

16:15 somnium`: yeah, I was so aggravated by juDate/effin' Calendar so that I'm now mapping all juDate's into joda-time DateTimes upon fetch.

16:15 which is clearly duplication

16:15 mongo people said they don't want any external deps, hence no joda-time, but it's "easy to serialize any type of your own"

16:15 chouser: alexyk: I suppose you could have a macro that emits a 'def' but without a body if *compile-files* is ture.

16:16 alexyk: chouser: interesting

16:16 somnium`: another issue: even if you fetch :only [:x], you get :_ns and :_id, which I always dissoc around fetch.

16:17 is there a flag to supporess :_ns and :_id?

16:17 suppress

16:18 KirinDave_: how do you insert gists into tumblr?

16:18 the-kenny: alexyk: There's a "embed" function on the gist site

16:18 You can just copy the html and insert it into the post

16:19 somnium`: alexyk: mongo *always* adds those keys, need them for save/update

16:19 alexyk: nice

16:19 the-kenny: alexyk: But they don't show up without javascript

16:19 somnium`: alexyk: could patch :only to take them off I suppose, but cant stop mongo from sending them

16:19 alexyk: somnium`: well I often don't plan upon returning the stuff to mongo, saving a transform as a new collection

16:20 somnium`: erally would like a flag :really-only or something, meaning no return to mongo

16:20 and hence no ns/id

16:20 somnium`: :really-only, I like it

16:20 alexyk: :)

16:22 somnium`: basically it would just drop ns/id, saving a (map #dissoc (fetch :coll :only [:x]) :_ns :_id) wrapper

16:22 hiredman_: why not put the id stuff in metadata?

16:22 somnium`: hmm, maybe a :no-mongo-keys flag?

16:23 alexyk: hiredman_: interesting angle

16:23 somnium`: sure... and also "mongo-as

16:23 -metadata

16:23 then :) for a choice

16:23 somnium`: hiredman_: no way to make metadata play nice with the .java driver :(

16:23 doublindirection: is there a way to specify "throws SomeException" with :gen-class :methods?

16:24 hiredman_: somnium`: but you already have a clojure layer betweeb clojure and the java right?

16:24 somnium`: Im kind of hacking on a clojure version but am handicapped by my total unfamiliarity with nio

16:25 alexyk: I can see how, if you really want to pu


16:25 hiredman_: the clojure layer can do a transform

16:25 alexyk: update mongo, you grab metadata back

16:25 somnium`: hiredman_: yes, but for performance it tries not to do much, just expose the api sanely

16:25 but it would be possible

16:25 alexyk: the fork is in your hands

16:25 alexyk: somnium`: after the PhD is in my hands next year :)

16:26 then I can even juggle with forks

16:26 for my clojure is hard at work with what is got... :)

16:27 somnium`: oh well, mongo is still kind of alpha until it gets concurrent reads anyway :)

16:28 alexyk: at least Ill be able to claim congo's been used by academics once you get your degree

16:29 alexyk: I thought about sharing with Haskell, which got no mongo srivers yet. But it has for couchdb and tokyo cabinet, but without JSON and shell, I can't fathom those beasts no more.

16:29 somnium`: ?

16:29 Licenser__: Hmm running in open doors here, but did everyone ever think about making a good documentation system for Clojure?

16:29 somnium`: how can you do anything with couchdb but not JSON?

16:29 alexyk: somnium`: after 6 months in scala, I added clojure, we'll see how it morphs. So far. clojure is best for data mining, and mongo is my store, with 100 gb of graph transforms.

16:30 Licenser__: I mean the doc strings are nice for hints but in the long run they can't replace a real documentation

16:30 alexyk: somnium`: I mean, with a shell. I didn't look too deep into it, but I need a mongo-liek shell to inspect, not a curl client.

16:30 somnium`: ah

16:34 jweiss: can someone recommend a way to write a clojure function like (defn myoldfn [] (do (mythis) (mythat) (myother) ) and then write mynewfn so that it reads basically as "call myoldfn but instead of mythat do myanotherThing"?

16:35 i'd like to keep the original function's steps written in order, in the fn, for readability

16:35 alexyk: somnium`: are there any shells for couchdb or tokyo cabinet comparable to mongo?

16:35 Chousuke: couldn't you parametrise myoldfn on mythat? :/

16:36 jweiss: Chousuke: yeah, but then the steps are written out of order

16:36 i want to keep it readable

16:36 Chousuke: out of order?

16:36 btw, the do in your example is redundant.

16:36 jweiss: it would execute in the right order or course, but mythat would be actually defined outside the function

16:37 Chousuke: defn bodies already have an implicit do

16:37 jweiss: Chousuke: sorry was just pseudocode

16:37 Chousuke: hmm

16:37 well, you can use binding I suppose

16:37 jweiss: Chousuke: i can't think of a way to do that and still keep the original fn as just a straightforward list of things to do

16:38 KirinDave_: alexyk: "How do you insert gists into tumblr?"

16:38 alexyk: You use the raw HTML view.

16:38 It's very bad that they let you do it, tbh

16:38 But you can put any script tag in.

16:38 jweiss: oh wait Chousuke i think i get it

16:38 Chousuke: jweiss: aren't you overdoing it a bit though? :/

16:38 alexyk: KirinDave_: I use markdown plugin for MarsEdit and Tumblr, usually

16:38 jweiss: (defn mynewfn (binding mythat (fn ... )))

16:38 KirinDave_: alexyk: I do not.

16:39 jweiss: Chousuke: yeah maybe

16:39 KirinDave_: alexyk: I just use the web interface (mostly the bookmarklet) for 90% of my stuff

16:39 Chousuke: jweiss: if the issue is with the order of defns, you can always declare a function first and define it later

16:40 jweiss: Chousuke: no that's not it, but in my domain i'm constantly sort of "patching" functions but i still need to keep the old ones around, and it gets totally unreadable

16:40 alexyk: somnium`: I tried googling for "couchdb shell"and only curl I see

16:40 jweiss: factoring out tiny bits into smaller fn's

16:40 alexyk: so a non-starter for me

16:40 Chousuke: jweiss: hm.

16:40 jweiss: was hoping macros or bindings could let me keep the original function looking basically the same

16:41 without copy/pasting

16:41 KirinDave_: So, is there documentation anywhere on the cont-m monad?

16:41 I really am having trouble understanding it.

16:41 And the base documentation is kinda sparse

16:41 Chousuke: jweiss: so you want a template for a function and then create functions based on replacing parts of that function?

16:42 jweiss: Chousuke: yep

16:42 Chousuke: jweiss: maybe you could make a function that takes a map of functions as a parameter.

16:42 jweiss: so somehow i need to mark the forms that need replacing

16:42 dysinger: KirinDave Jim Duey has some tutorials on it.

16:42 Chousuke: jweiss: and then just pass in different function maps to it.

16:42 yielding new functions.

16:42 KirinDave_: dysinger: Could you point me to a link?

16:42 dysinger: http://intensivesystems.net/tutorials/cont_m.html

16:43 KirinDave_: Damn

16:43 jweiss: Chousuke: but again, that still involves taking the template apart too, doesn't it?

16:43 KirinDave_: I just cannot navigate that guy's site.

16:43 I keep going to it and failing to read it.

16:43 * KirinDave_ is shamed

16:43 Chousuke: jweiss: well the "template" would become a function that takes the values from the map and does something with them

16:44 jweiss: Chousuke: yeah but i was hoping that my original unpatched template would remain intact. to do what you're saying, i'd have to refactor it

16:44 and pull out all the parts that get overridden

16:45 and put them into that map

16:45 Chousuke: yeah.

16:45 you can also make the "generic" parts into a macro

16:46 then your original function is just one expansion of that macro.

16:47 jweiss: Chousuke: hm, that might be ok, at least macroexpand should show me an easier to read fn

16:48 Chousuke: I can give only very general advice, but when writing a macro you're basically designing a new syntax for writing these functions (whatever they are)

16:48 so make the most out of it

16:51 somnium``: alexyk: Im not too familiar with couch, Ive only used futon

16:52 jweiss: Chousuke: seems like i need the source fn here

16:52 alexyk: somnium``: is futon as convenient as mongo client?

16:52 somnium``: alexyk: but Im sure there are people here who are quite knowledgeable

16:53 alexyk: its a web app, not really comparable I guess

16:53 alexyk: knowledgeable people: does couchdb have a shell where you can easily inspect data?

16:53 :)

16:55 danlarkin: Greetings clojurecrats! I'm back with another connundrum: why do these following two expressions not behave the same?

16:55 ,(let [f #(compare (:x %1) (:x %2))] (= {{:x 1 :name "juan"} 1} (sorted-map-by f {:x 1 :name "dan"} 1)))

16:55 clojurebot: true

16:55 danlarkin: ,(let [f #(compare (:x %1) (:x %2))] (= (sorted-map-by f {:x 1 :name "dan"} 1) {{:x 1 :name "juan"} 1}))

16:55 clojurebot: false

16:57 hiredman: I wonder if clojars could have an rss feed

16:58 Chousuke: danlarkin: why does the first one return true... huh. weird.

16:59 hiredman: non-semetrical equality

16:59 it happens

16:59 danlarkin: it shouldn't! (imo)

16:59 hiredman: correct

17:01 chouser: alexyk: I just put together a down-and-dirty, mutable-array-based schwarzian transform sort, and I can't get it to beat clojure's sort-by

17:02 danlarkin: can't figure out why = isn't commutative from a quick browse of the java code

17:03 chouser: alexyk: which is interesting because the keyfn I'm testing it on is the one I gave you, where it's creating a 2-element vector for every call.

17:04 Chousuke: danlarkin: did you check both sorted-map and the persistent map?

17:04 technomancy: is there a trick to creating a clojure map from a java.util.Map?

17:04 Chousuke: technomancy: (zipmap (keys themap) (vals themap)) perhaps?

17:05 maybe even just (into {} themap)

17:05 technomancy: Chousuke: oh wow; into works great

17:05 thanks

17:05 chouser: I would have that that was sufficiently expensive for the transforming sort to win

17:05 technomancy: that'll clean things up nicely

17:06 alexyk: chouser: in my case, vectors are really vectors of pairs, and I sort by e.g. sum of the second elements. E.g. [["bob [[1 1] [2 3] [3 2] [4 2]]] ["alice [[0 2][3 2][5 5]]] ...]

17:07 danlarkin: Chousuke: well PersistentTreeMap doesn't implement equiv or equals, so that'd fall back to APersistentMap

17:07 hiredman: fyi Properties implement java.util.Map

17:07 alexyk: hence sort-by, blazing fast on such 3.5 million pairs, is just: (sort-by (fn [[k v]] [(- (apply + (map second v))) k]) sper-days)

17:08 chouser: following your trick

17:09 danlarkin: Chousuke: and clojure.core/= uses clojure.lang.Util/equiv for comparison, which uses IPersistentCollection.equiv

17:09 and that's where I lose it

17:09 alexyk: I was really surprised by speed, unless the map/fn is computed only once

17:11 hiredman: I think you are following the wrong direction

17:11 I would check the equiv on sorted maps

17:12 danlarkin: but it's when the non-sorted map comes first that = is wrong

17:13 somnium``: alexyk: what is the average num of keys in the maps youre crunching?

17:13 alexyk: the ones coming from the db I mean

17:14 hiredman: danlarkin: but sorted-map was added later so it's equivilance semantics are more likely to need some adjusting

17:14 alexyk: somnium``: from 1 to 30,000 currently

17:14 each element, 3-10 million elements per coll

17:14 brb

17:15 hiredman: huh

17:15 ~def sorted-map

17:16 somnium``: alexyk: egads, youre storing objects with 30,000 keys?

17:16 hiredman: hmmm

17:18 danlarkin: the counts don't even have to be the same:

17:18 ,(let [f #(compare (:x %1) (:x %2))] (= {{:x 1 :name "juan"} 1} (sorted-map-by f {:x 1} 1)))

17:18 clojurebot: true

17:19 chouser: ,(map first (sorted-map-by #(compare (:x %1) (:x %2)) {:x 1 :name "dan"} 1))

17:19 clojurebot: ({:x 1, :name "dan"})

17:19 chouser: ,(map first (sorted-map-by #(compare (:x %1) (:x %2)) {:x 1 :name "dan"} 1 2 3 4 5))

17:19 clojurebot: (2 {:x 1, :name "dan"})

17:19 chouser: oh, wait.

17:19 somnium``: is there a summary of performance characteristics for ArrayMap vs. StructMap vs. HashMap vs. DynamicType anywhere+ (creation, look-up, etc.) ?

17:19 chouser: sorry, I was off the tracks there.

17:21 ah, there it is.

17:21 danlarkin: right, so I think the problem must live in APersistentMap:

17:21 ,(let [f #(compare (:x %1) (:x %2))] (.equiv {{:x 1 :name "juan"} 1} (sorted-map-by f {:x 1} 1)))

17:21 clojurebot: true

17:21 chouser: ,(get (sorted-map-by #(compare (:x %1) (:x %2)) {:x 1 :name "dan"}) {:x 1 :name "anything at all"})

17:21 clojurebot: java.lang.IllegalArgumentException: No value supplied for key: {:x 1, :name "dan"}

17:22 chouser: ,(get (sorted-map-by #(compare (:x %1) (:x %2)) {:x 1 :name "dan"} 1) {:x 1 :name "anything at all"})

17:22 clojurebot: 1

17:22 danlarkin: ah ha

17:22 chouser: sorted maps use the comparator to find the value

17:23 perhaps they should do a final equality check of the key before succeeding?

17:23 or perhaps not. I dunno.

17:23 danlarkin: well it seems like they ought to

17:24 at least it seems tome that the current behavior is wrong

17:24 chouser: well, this seems wrong too but has been ruled Not A Bug:

17:24 ,{:a 1 :a 2 :a 3}

17:24 clojurebot: {:a 1, :a 2, :a 3}

17:25 danlarkin: yeah but that's in such a corner case

17:25 chouser: using a comparator for sorted-map-by that claims two values are equal when they are not seems like a corner case too, doesn't it?

17:26 danlarkin: I don't want the comparator to be used for equality, just sorting :)

17:26 Chousuke: isn't the sorting ... right.

17:26 reify: what clojure-contrib branch is recommended for clojure 1.x ?

17:27 chouser: reify: master, I think. for now. :-)

17:27 reify: i get these errors when compiling clojure-contrib with a clojure-1.1.jar: java.lang.NoSuchMethodError: clojure.lang.RestFn: method <init>()V not found (PrettyWriter.clj:17)

17:28 chouser: reify: "ant clean" first

17:29 reify: i swore I did that, thanks, that worked

17:30 chouser: reify: that's my job: telling you what you already know.

17:30 :-)

17:31 danlarkin: so my workaround right now is to make sure the order to clojure.core/= always puts the sorted-map first... do you think this is worthy of escalating? (I do)

17:32 chouser: sure. I just wouldn't be shocked if the answer is "well, don't do that"

17:32 danlarkin: I hate those answers :(

17:33 alexyk: somnium``: sorry, each object has usually one key. The value may be a longish vector or submap, tho.

17:34 hiredman: ~RestFn

17:34 clojurebot: Gabh mo leithscéal?

17:34 hiredman: ~clojure.lang.RestFn

17:34 clojurebot: ant clean and rebuild contrib

17:35 somnium``: alexyk: congo creates hash-maps by default, but would be pretty easy to add an array-map flag for smallish maps.

17:37 chouser: technomancy: is it too hard to make your comparator only return 0 when keys are equal?

17:38 except I've gotta run, so we can pretend that was rhetorical. :-)

17:38 danlarkin: chouser: I assume you meant me :)

17:38 somnium``: does the reader decide between array-map/hash-map by just counting key-value pairs?

17:38 chouser: danlarkin: right! sorry!

17:38 technomancy: sorry!

17:39 somnium``: reader always uses array-map, I believe. assoc/dissoc count keys and switch formats appropriately.

17:39 uh. except I'm wrong.

17:39 somnium``: hmm

17:40 ? :)

17:41 chouser: well, I do have to go. Ignore what I said. :-P

17:48 mabes: is there a way to require/use all of clojure/contrib? I would like to use (find-doc) on all of it...

18:28 joshua-choi: Hey, is there a better way to add an object x to the beginning of a vector v than (vec (cons v x))?

18:29 hiredman: I don't imagine so

18:30 you could implement your own type of vector that allowed adding to the front some how

18:31 for key 0 return x else return element key - 1 from vector v

18:32 joshua-choi: Well, I'm not sure I want to go that far

18:32 I'm worried that with vec and cons, though, creating a sequence from a vector, and then a new vector from the sequence would be more inefficient than may be necessary

18:32 Chousuke: you could pester chouser to finish the finger tree implementation and make a deque :P

18:32 hiredman: vectors were not designed with effecient adding tothe front in mind

18:33 joshua-choi: Yeah...maybe I should try to change my logic so I don't have to add to a vector's beginning, ugh

18:34 chouser: there's a PersistentQueue if you just want to always add to the right and take from the left.

18:34 joshua-choi: In clojure.core?

18:34 hiredman: ,(conj clojure.lang.PersistentQueue/EMPTY 1)

18:34 clojurebot: (1)

18:34 hiredman: ,(conj clojure.lang.PersistentQueue/EMPTY 1 2)

18:34 clojurebot: (1 2)

18:35 hiredman: ,(peak (conj clojure.lang.PersistentQueue/EMPTY 1 2))

18:35 clojurebot: java.lang.Exception: Unable to resolve symbol: peak in this context

18:35 hiredman: ,(peek (conj clojure.lang.PersistentQueue/EMPTY 1 2))

18:35 clojurebot: 1

18:35 joshua-choi: I had no idea that this data structure existed

18:35 Chousuke: it's not very well documented :/

18:36 hiredman: I think rhickey has some (evil?) mastermind plans for queues

18:39 joshua-choi: Ah, I just came up with a way to avoid adding to a vector's beginning; I guess that's best

18:39 I've got another question though

18:39 According to http://gnuvince.wordpress.com/2009/05/11/clojure-performance-tips, using destructuring in let (and so, probably fn too) is pretty slow

18:39 That post was from earlier this year; is it still the case?

18:40 Should I avoid destructuring lets in loops, etc?

18:42 the-kenny: joshua-choi: Only if you have a real bottleneck at this point in your code

18:42 danlarkin: joshua-choi: measure and THEN optimize :)

18:42 the-kenny: first: write it beautiful, if it's to slow, write it faster

18:42 s/to/too/

18:44 joshua-choi: Yeah, that makes sense

18:44 I have no idea have to measure though

18:44 I'm not experienced with profiling Clojure, or anything for that matter

18:45 hiredman: it's a complex macro

18:45 the-kenny: joshua-choi: Just write your code.. if you don't notice that the code is too slow, there's no need to change the code for more speed

18:49 ubii: anyone using clojure for web development?

18:50 the-kenny: ubii: Yeah, some people here. Just ask your question :)

18:51 ubii: what framework(s) are most folks using and how production ready are they?

18:51 the-kenny: ubii: I think compojure is the most prominent framework here. http://clojars.org is running on it

18:53 mtm: chouser: you're to the point of picking a title and cover for the book? Sounds like you're almost done... (rubs hands gleefully in anticipation)

18:54 ubii: out of the frameworks that I look at so far, compojure looks the most interesting

18:55 tomoj: compojure is changing currently I think?

18:55 ubii: in what way?

18:56 tomoj: being refactored I think

18:56 ubii: ah

18:56 tomoj: dunno how far away that stuff is from master

18:57 ubii: one thing that I am trying to get a better grasp on is the server side of things, such as how to best deploy multiple sites on a single server

18:59 tomoj: I guess that kind of thing is java's problem

18:59 ubii: as well, as which web/app server(s) to, in order to maximize scalability

18:59 understood

18:59 tomoj: I don't know much about that yet either

18:59 hiredman: you can always proxy requests via apache

19:00 tomoj: I asked before whether there is a need to run multiple instances of the application on a single server (like we have in ruby), and the answer was 'no'

19:01 I guess because java can actually do threading

19:01 hiredman: yeah, there isn't, but it makes it easier

19:01 makes it

19:01 tomoj: wait, what?

19:01 that only sounds harder to me

19:01 hiredman: compojure has the run script right? for developement that launches with jetty?

19:02 (it's been a while)

19:02 so you do that once per site, each site gets a port, set up the forwarding in an apache config

19:02 ubii: if for example, say I have different sites, running on the same server, do each of them run under their own JVM?

19:02 hiredman: it's not perfect by along shot, but it is dead simple

19:03 tomoj: right, that sounds easy

19:03 I meant how like with ruby we might proxy apache/nginx to multiple running copies of the application even on the same server

19:03 only have to do one here, I think

19:05 * hiredman deploys to appegine and doesn't think about it

19:09 ubii: just trying to get some idea of what type of memory resources each site might require, using something like compojure

19:09 hiredman: compojure has a google group

19:12 ubii: np, I can pop on #compojure and ask

19:14 was just trying to get a feel for what most folks were using and how to best setup multiple sites up on a single server

19:14 thx

19:55 defn: how do you get a coll you turned into a transient back?

19:55 hiredman: (doc persistent!)

19:55 clojurebot: "([coll]); Returns a new, persistent version of the transient collection, in constant time. The transient collection cannot be used after this call, any such use will throw an exception."

19:56 defn: awesome thanks

19:58 what is [b] in clojure?

19:58 Chousuke: a vector of one element?

19:58 defn: ,(doc chunk)

19:58 clojurebot: "([b]); "

19:58 Chousuke: aha. :D

19:58 hiredman: yep

19:58 Chousuke: good documentation. don't ask me.

19:59 it means the function takes one argument, named b :P

19:59 whatever that is.

19:59 defn: bahaha

19:59 goddamnit

19:59 hiredman: ,(alter-meta! #'chunk assoc :arglists _

19:59 clojurebot: EOF while reading

19:59 hiredman: ,(alter-meta! #'chunk assoc :arglists _)

19:59 clojurebot: java.lang.Exception: Unable to resolve symbol: _ in this context

19:59 hiredman: ,(alter-meta! #'chunk assoc :arglists '_)

19:59 clojurebot: {:ns #<Namespace clojure.core>, :name chunk, :file "clojure/core.clj", :line 446, :arglists _}

19:59 hiredman: (doc chunk)

19:59 clojurebot: "_; "

19:59 defn: ah i see

20:02 map and filter use the chunk stuff

20:02 cool

20:04 ericlavigne: Just installed NetBeans+Enclojure but Clojure isn't one of the options for new project types. Have I configured wrong, or should I be creating a Java project and putting Clojure source in it?

20:54 devlinsf: Is is possible to get bug fixes in for 1.1?

20:55 hiredman: I would imagine so

20:55 devlinsf: I have a fix for 128

20:55 just posted

20:56 Can someone review?

21:18 hiredman: // int WIDE = 196; // NOT VISITED

21:18 :(

21:21 devlinsf: ???

21:22 hiredman: WIDE is the bytecode the experimental jvm uses to annotate tail calls

21:23 and WIDE is commented out in the source of Opcodes.java in the asm library

21:27 devlinsf: Oh

21:28 So no TCO?

21:29 hiredman: I don't know the asm lib too well

21:32 uncommenting it and trying to use wide just gives me a NPE

21:32 devlinsf: Hmmm

21:34 alexyk: how do I take last N elements of a collection?

21:35 devlinsf: currently not supported

21:35 alexyk: grrr

21:35 devlinsf: I'd do this

21:36 (defn take-last [n coll] (drop (- (count coll) n) coll))

21:36 Gonna talk about that fn for 1.2

21:36 alexyk: nice

21:36 devlinsf: We'll see where it goes

21:36 hiredman: ,((comp first drop-while) (comp (parial = 6) count) (iterate rest (range 10)))

21:36 clojurebot: java.lang.Exception: Unable to resolve symbol: parial in this context

21:36 hiredman: ,((comp first drop-while) (comp (partial = 6) count) (iterate rest (range 10)))

21:36 clojurebot: (0 1 2 3 4 5 6 7 8 9)

21:37 hiredman: bleh

21:37 alexyk: may call it tail as well

21:37 hiredman: ,((comp first drop-while) (comp (partial not= 6) count) (iterate rest (range 10)))

21:37 clojurebot: (4 5 6 7 8 9)

21:37 devlinsf: Yeah, expect there already is drop-last

21:37 hiredman: ,((comp first drop-while) (comp (partial not= 6) count) (iterate rest (range 1000)))

21:37 clojurebot: (994 995 996 997 998 999)

21:37 devlinsf: maybe alias it as tail?

21:37 alexyk: and alias take as head

21:38 unless it's taken

21:38 devlinsf: ~head

21:38 clojurebot: No entiendo

21:38 devlinsf: NOpe

21:42 defn: alexyk: you coulkd just reverse it

21:42 could just*

21:43 alexyk: true too

21:43 defn: ,(take 10 (reverse (range 0 21)))

21:43 clojurebot: (20 19 18 17 16 15 14 13 12 11)

21:43 defn: i like reverse the most -- seems easiest to understand

21:43 im not sure about its effect on performance, though

21:43 alexyk: defn: then reverse again

21:44 hiredman: also the worst O

21:44 devlinsf: hiredman: true

21:44 hiredman: clojurebot: the most horrible thing?

21:44 clojurebot: most horrible thing is http://tinyurl.com/b65o8e

21:44 alexyk: hiredman: yours is Greek to me :)

21:45 what's comp first drop-while do?

21:45 devlinsf: (first (drop-while ...

21:47 alexyk: right, still it's puzzling.

21:48 defn: the loop seems ugly

21:48 err, look ugly in *my* opinion

21:48 alexyk: how do you limit the size of output by clojure repl?

21:48 defn: looks*

21:48 alexyk: good question, id be interested to know that

21:48 alexyk: trying to depuzzle hiredman's stuff from the tail produced a sea of numbers

21:49 jasapp: alexyk: do you mean *print-length*?

21:49 alexyk: ah

21:49 jasapp: (set! *print-length* 10)

21:49 hiredman: (iterate rest (range 3)) => ((0 1 2 ) (1 2) (2) () ...)

21:49 devlinsf: \me wants to slap the "lisp w/o parens" crowd

21:50 * devlinsf wants to slap the "lisp w/o parens" crowd

21:50 devlinsf: There

21:50 jasapp: I've always wondered how to do that

21:50 devlinsf: /me

21:50 * jasapp must try

21:50 jasapp: sweet

21:51 * alexyk welcolmes jasapp to the sotto voce club

21:51 jasapp: heh

21:51 defn: jasapp: nice

21:51 thanks

21:51 alexyk: hiredman: what's ...? I'm afraid for my repl

21:52 jasapp: it just prints ...'s

21:52 hiredman: it goes on forever

21:52 hmmm

21:52 actually

21:52 defn: clojurebot: sotto voce is <reply>shhhh!

21:52 clojurebot: Alles klar

21:52 hiredman: nuts, mine depends on count

21:53 so mine is n*n'ish

21:53 alexyk: yeah, it's darn many numbers it generates

21:53 jasapp: I thought most structures held their count somewhere

21:53 hiredman: not seqs

21:54 defn: ,(doc ref-max-history)

21:54 clojurebot: "([ref] [ref n]); Gets the max-history of a ref, or sets it and returns the ref"

21:59 alexyk: hmm:

21:59 .(doc take-last)

21:59 ,(doc take-last)

21:59 clojurebot: "([n coll]); Returns a seq of the last n items in coll. Depending on the type of coll may be no better than linear time. For vectors, see also subvec."

22:00 devlinsf: Hmmm?

22:00 alexyk: rhickey beamed it from the future

22:00 hot-loaded erlang-style into clojurebot by the firedman of 2012 :)

22:00 * alexyk kidding

22:01 devlinsf: Still confused

22:01 alexyk: me too

22:01 jasapp: that makes three of us, at least

22:02 alexyk: I found it by trying to load devlinsf's take-last into the current ns, got confict with clojure.core/that

22:02 devlinsf: I could swear this wasn't there yesterday....

22:02 Oh well

22:02 Musta made a mistake

22:41 joshua-choi: ,(syntax-quote conj)

22:41 clojurebot: java.lang.Exception: Unable to resolve symbol: syntax-quote in this context

22:42 joshua-choi: Is there a form for syntax quoting, like (quote x)?

22:44 hiredman: there maybe a dummy stubbed out in core, but syntax quote is currently a reader macro, so having it won't work like that

22:45 joshua-choi: I see

22:46 But, I could do

22:46 ,(first `(conj))

22:46 clojurebot: clojure.core/conj

22:46 joshua-choi: but it looks messy

22:47 Is there a better way?

22:47 hiredman: ,(resolve 'conj)

22:47 clojurebot: #'clojure.core/conj

22:47 joshua-choi: Excellent; would that work in macros?

22:47 hiredman: you could also just

22:48 ,`conj

22:48 clojurebot: clojure.core/conj

22:49 joshua-choi: Well, it's in a function: it's an argument whose value (a symbol) needs to be resolved

22:49 hiredman:

22:49 actually resolve resolves to the var

22:50 resolved or namespace qualified?

22:50 resolve resolves, and ` namespace qualifies, not resolves

22:50 joshua-choi: Well, namespace qualified, but like syntax quoting—which implies sort of resolving, right?

22:51 hiredman: maybe "quasi-resolving"

22:52 joshua-choi: I need it in a function that looks like this: (f [name] [(keyword name) (something name)]) so that (f 'conj) -> [:conj 'clojure.core/conj]

22:54 hiredman: ,(ns-map *ns*)

22:54 clojurebot: {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, val #'clojure.core/val, ProcessBuilder java.lang.ProcessBuilder, chunked-seq? #'clojure.core/chunked-seq?, Enum java.lang.Enum, find-protocol-impl #'clojure.core/find-protocol-impl, SuppressWarnings java.lang.SuppressWarnings, *compile-path* #'clojure.core/*compile-path*, max-k

22:54 hiredman: hmmm

22:55 are you sure you want the namespace qualified symbol and not the var?

22:55 joshua-choi: Well, the var would work too, come to think of it

22:56 Yes, using var works! Excellent, thanks for the help

22:56 hiredman: ,(reduce #(conj %1 (keyword (name (key %2))) (val %2)) {} (ns-map *ns*))

22:56 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword

22:57 hiredman: ,(reduce #(conj %1 [(keyword (name (key %2))) (val %2)]) {} (ns-map *ns*))

22:57 clojurebot: {:StackTraceElement java.lang.StackTraceElement, :unchecked-inc #'clojure.core/unchecked-inc, :ArithmeticException java.lang.ArithmeticException, :import #'clojure.core/import, :deliver #'clojure.core/deliver, :symbol #'clojure.core/symbol, :vals #'clojure.core/vals, :print-doc #'clojure.core/print-doc, :select-keys #'clojure.core/select-keys, :re-matcher #'clojure.core/re-matcher, :rand #'clojure.core/rand, :deref #'cloj

22:57 hiredman: anyway, resolve will get you the var

Logging service provided by n01se.net