#clojure log - Oct 06 2009

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

1:13 slyrus_: hmm... what's the idiomatic approach when one feels like the would normally use CL's return-from construct?

1:56 konr: should I read Let Over Lambda? Is it relevant to clojure programming?

2:00 sdeobald_: I don't have stu's book in front of me and my googling is failing me. How can (may?) I bind an anonymous function so that it can call/recurse on itself?

2:03 slashus2: (fn functionname [] (functionname))

2:04 sdeobald: ^

2:04 * sdeobald_ slaps face

2:04 sdeobald_: Thanks.

2:05 slashus2: Or you can use recur

2:06 sdeobald_: I'm actually making a weak attempt at converting an SICP exercise, so recur might be cheating and/or going too far.

2:11 hiredman: well, if you are doing sicp you might want to find a copy of the Y combinator

2:30 sdeobald_: hiredman: is there a book/paper by that name, specifically? Or do you just mean the concept in general?

2:31 If anyone's interested: http://github.com/deobald/sicp-clojure/blob/master/1.1/sec_1_1_8.clj

2:31 I'd love to hear thoughts on how to make the re-binding of 'sqrt-iter' go away.

2:37 hiredman: no paper, I think someone implemented a clojure version on the google group

2:38 sdeobald_: Cool, thanks.

2:38 hiredman: well, no paper I was specifically refering to

2:38 sdeobald_: Gotcha

3:13 Fossi: hi

3:41 jdz: sdeobald: what rebindingL

3:41 ?

3:41 sdeobald: and i'm pretty sure you want to use recur

4:13 Maddas: sdeobald: If you want to read up on the Y combinator, there's a paper titled "The Why of Y"

4:47 konr: What do you think of Common Lisp?

4:49 Chousuke: I tried it when I first heard about lisp but I never really got into it :/

4:52 LauJensen: konr: Coming from C# to CL it has very thrilling. Coming from Clojure to CL it will feel very out dated and moronic

4:52 s/has/was

4:53 jdz: well, after doing some work stuff in Clojure for last 3 or so months coming back to CL seems like a dream come true, really

4:54 i never thought i would be so happy seeing a real backtrace

4:54 LauJensen: jdz, why ?

4:54 Raynes: I saw that coming.

4:54 jdz: with restarts

4:54 just my experience, yours will vary

4:54 yason: konr: It's more complex than I would desire from a language, and practically has no standard environment and libraries to run with (think Python, Java). But it has good, novel things too, if you're willing to immerse into it.

4:55 * Raynes barely scratched the surface with CL.

4:55 Raynes: I've got everything I need with Clojure. <3

4:55 jdz: except a backtrace you can find useful information in :/

4:56 Chousuke: backtraces in Clojure are horrible, yes :P

4:56 Raynes: jdz: I don't need that.

4:56 \o/

4:56 Chousuke: my reader (which I still have to finish) have me exceptions wrapped in about 20 layers of RuntimeException for some reason ;(

4:57 I wish I had more time to work on Clojure stuff now

4:57 I'm always getting distracted by something else I need to do

4:58 Raynes: Chousuke: Let's build that time machine I designed back in '02, and we can do just that.

4:58 Chousuke: Raynes: we can go back in time and incorporate cool Clojure features in Common Lisp.

4:59 Raynes: Chousuke: Or we can kill all those associated with the creation of Common Lisp and create a Lisp with Clojure characteristics in it's place, and then return to the future to see how we modified the future.

4:59 Chousuke: that's a bit drastic.

5:00 Raynes: Yes, but what do we have to lose?

5:00 We can just go back and not kill them.

5:00 Besides that, they shall not die in vain.

5:00 Chousuke: The creators of CL are still smart people. they would be more useful if we brainwashed them

5:00 * Raynes goes to bed, before he ends up in prison for attempted murder.

5:01 jdz: Raynes: if you see Common Lisp around like it is, it means you have not gone back from the future and have not corrected the past

5:01 easy as that

5:02 Chousuke: actually, if you changed the future you would forget that it ever was different

5:02 so you'd think you had failed.

5:02 Maddas: Clearly none of you saw Star Trek (the recent movie).

5:02 Raynes: Not necessarily.

5:02 There would be new versions of ourselves when we return to the future, but we should still remain.

5:02 Anyways, I'm actually going to bed, goodnight <3.

5:03 konr: bye

5:07 LauJensen: jdz, I must say I'm surprised that after using STM, atoms, agents, java libs and vector bindings that you would want to go back to CL

5:07 jdz: LauJensen: in the application domain i use i have no use for those, really. like, interfacing with a foreign code that is not thread-safe

5:08 and java libs suck balls

5:08 oh, did i say that out loud?

5:36 Chousuke: gah :(

5:37 terminal crashed while I was compiling emacs

5:50 LauJensen: Chousuke, where's your reader?

5:51 Chousuke: still on github :P

5:52 LauJensen: link?

5:53 Chousuke: lazy, huh :P

5:53 http://github.com/Chousuke/clojure/tree/clojure-reader

5:54 the next step would be to make Clojure actually use it but that requires messing with the java code and I'm not quite sure how to proceed :/

5:54 LauJensen: lazy?? What does it take nowadays to search for 'Chousuke', then bring up your 'clojure-reader' project, 10 minz?

5:55 Chousuke, I'm sure the Group can answer that question, ie. Rich is there

5:56 I see you didn't do a reader.clj - which files have you worked with ?

5:56 Chousuke: it's in src/clj/clojure/lang/reader.clj :P

5:56 LauJensen: aah gotcha :P

5:57 Chousuke: it's also based on my syntax-quote-macro modification of core.clj, which is on its own in the sq-macro branch

5:58 LauJensen: Why *black-hole* ?

5:58 Chousuke: I just needed something I could conj onto that ignores the item

6:00 LauJensen: Chousuke, Are you away that you can actually put documentation directly in the source, the so-called doc-strings? When you have function names like 'make-rh', 'quick-rh', etc, it really speeds up reading for other people looking at your source

6:00 s/away/ware

6:00 s/ware/aware

6:00 Chousuke: yes. I might document it later.

6:00 Fossi: "might" xD

6:00 Chousuke: the make-rh stuff will probably go away anyway

6:01 LauJensen: I'll commend you on your brevity of source, but it's really lacking in 1) no documentation, 2) an abundance of 'magic' numbers

6:02 Chousuke: you mean the parameters to the advance function?

6:03 LauJensen: More like "(<= 0xD800 ch 0xDFFF)" "(and (== 5 (count string)) (try (Integer/parseInt (subs string 1) 16)" "(not (<= 0 ch 0377))" etc

6:03 Chousuke: oh, right. that.

6:03 that's directly copied from the Java Reader. :)

6:03 though hm, I think it had comment s :P

6:03 -s

6:03 er, -' ' I mean

6:03 LauJensen: hehe

6:05 Chousuke: the symbol resolution stuff in the keyword handling is icky

6:06 there seems to be no good way to resolve a symbol to its full form without many conditionals ;/

6:10 hmm

6:10 I'm using #() in the definition of the #() implementation function :P

6:10 I wonder if I'll have to fix that.

6:14 danlei: not if you're compiling clojure to clojure :p

7:58 licoresse: What is the best tool for looking up stuff in java doc?

7:58 LauJensen: I recommend: Your eyes

7:59 licoresse: haha

7:59 LauJensen: ;)

7:59 licoresse: I remember a site, in the beginning of 2000, that let you search for keywords and presented examples where the keyword was present

8:00 it was a great tool

8:00 LauJensen: Google you mean ?

8:01 licoresse: LauJensen: no... not goggle

8:02 konr: What's the clojure equivalent of CL's find-all?

8:04 select!

8:14 LauJensen: licoresse, I can't determine if you're being serious or not - What tool could you want to go through a Javadoc? You always know which classes your looking, and a simple search gives you the description. What more is there?

8:15 licoresse: Ah, my point was *examples*

8:15 LauJensen: aaah

8:15 licoresse: getting related examples to the Canvas class f.ex

8:15 hehe

8:16 *eyes*

8:16 chouser: http://www.google.com/codesearch?q=Canvas+lang:java

8:17 licoresse: ah nice!

8:18 LauJensen: The first example is real nice, couldn't be any clearer than a one-liner

8:19 chouser: yeah, it's an excellent example of Java

8:19 public static final i forgot what i was doing...

8:46 LauJensen: It's funny that my first version of brians brain attracted thousands of readers, but my transient rewrite has barely had 200 views :)

8:47 ambient: it might have something to do where it was linked

8:47 visibility is king

8:48 LauJensen: I know - But I don't do anything to promote it, except put it on dzone, just to see what happends naturally

8:49 Chousuke: LauJensen: I don't see you in the clojure pipe ;(

8:50 LauJensen: There's a Clojure pipe? :)

8:50 Chousuke: yes

8:51 ambient: the original post is linked on reddit, the second one is not

8:51 LauJensen: Yea, I wonder why

8:57 konr: Hmmm, should I change a value set by (bindings)?

8:57 *(binding)

8:57 LauJensen: konr, in which situation ?

9:02 konr: LauJensen: I'm adapting some CL code that has several functions that access global variables. These variables can be overridden at a main function, so I'm not sure whether I should override them with (binding) or use references, setting them at the main function

9:03 LauJensen: konr, I think you need to think the design through before you start coding, a 1-to-1 translation will probably give you very bad looking clojure code. If you're loading settings, it might be better to stuff them all in a hash-map, rather than have 100 global defs etc.

9:05 Chousuke: if your code is (or will be) threaded you must also take that into account.

9:10 LauJensen: yes, then you're looking at refs or atoms

9:14 Chousuke: I guess you could use alter-var-root though :/

9:14 if it really is one-time configuration

9:17 LauJensen: ,(doc alter-var-root)

9:17 clojurebot: "([v f & args]); Atomically alters the root binding of var v by applying f to its current value plus any args"

9:17 LauJensen: Never used that

9:20 Chousuke: chouser showed a neat use of it on the group

9:20 hmm

9:21 LauJensen: got link ?

9:21 Chousuke: well, it was just (alter-var-root #'somefunc memoize)

9:22 * Chousuke wonders what would happen if he did that to print in Clojurebot...

9:23 Chousuke: ,`defang

9:23 clojurebot: sandbox/defang

9:23 Chousuke: not visible in the sandbox I guess ;(

9:23 clojurebot: source

9:23 clojurebot: source is http://github.com/hiredman/clojurebot/tree/master

9:24 Chousuke: ,`de-fang

9:24 hm.

9:24 clojurebot: sandbox/de-fang

9:24 Chousuke: ,#'hiredman.sandbox/de-fang

9:24 clojurebot: #'hiredman.sandbox/de-fang

9:25 Chousuke: ,(alter-var-root #'hiredman.sandbox/de-fang (fn [x] identity))

9:25 clojurebot: #<core$identity__4657 clojure.core$identity__4657@1e07f4b>

9:25 Chousuke: ,(defn foo [x] x)

9:25 clojurebot: Wrong number of args passed to: core$identity

9:25 Chousuke: oops

9:25 :(

9:25 hiredman: sorry, I broke clojurebot

9:25 hiredman: but you need to fix that hole

9:29 hiredman: you need to make the defang function and the *bad-forms* global local to the sanbox-eval function :P

9:32 hmm

9:32 ,#=(alter-var-root #'hiredman.sandbox/de-fang (fn [x] (fn [form _] form)))

9:32 clojurebot: clojure.lang.Cons cannot be cast to clojure.lang.Var

9:34 Chousuke: ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) (fn [x] (fn [form _] form)))

9:34 clojurebot: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

9:34 Chousuke: ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn [x] (fn [form _] form)))

9:34 clojurebot: clojure.lang.Cons cannot be cast to clojure.lang.IFn

9:34 Chousuke: gah

9:34 ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn [x] #=(fn [form _] form)))

9:34 clojurebot: clojure.lang.Cons cannot be cast to clojure.lang.IFn

9:35 Chousuke: I suppose I can't fix it :(

9:36 ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(fn* [x] #=(fn* [form _] form)))

9:36 clojurebot: Can't resolve fn*

9:37 Chousuke: ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(eval '(fn [x] (fn [form _] form))))

9:37 clojurebot: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

9:38 Chousuke: ,#=(alter-var-root #=(var hiredman.sandbox/de-fang) #=(eval (fn [x] (fn [form _] form))))

9:38 clojurebot: #<sandbox$eval__2941$fn__2943$fn__2945 sandbox$eval__2941$fn__2943$fn__2945@1ab5e85>

9:38 Chousuke: hmm

9:39 ,4

9:39 clojurebot: 4

9:39 Chousuke: hooray

9:42 this particular security hole is really nasty though :(

9:44 might be better to kill Clojurebot before anyone really exploits it :P

9:50 liwp: Chousuke: remind me: what does #= do?

9:50 Chousuke: read-time evaluation

9:50 that's not the main security hole though.

9:50 liwp: nope

9:50 Chousuke: the real hole is that I can override the sanboxing function...

9:51 sandboxing*

9:51 liwp: I was just trying to figure out how you fixed clojurebot

9:51 after breaking it

9:51 Chousuke: well, I notice that clojurebot doesn't bind *read-eval* to false

9:52 I'm still contemplating whether I should just kill Clojurebot or wait till hiredman responds ;(

9:53 noticed* ;P

9:54 I think it would be useful if you could mark vars as truly immutable

9:54 liwp: definitely in this case

9:55 Chousuke: but there are problems with that, too I guess.

9:55 liwp: it's also against the dynamic nature of lisp

9:55 but that's more of a philosophical argument

9:56 Chousuke: I wonder if the bound-fn macro could help.

9:56 liwp: I haven't really been following the bound-fn conversation so far

9:56 I've never really been bitten by laziness in clojure so I haven't cared

9:57 Chousuke: though because you can basically change any var to anything it won't help much ;(

9:57 and somehow I doubt there's a way to disallow all possible ways of changing a var without crippling clojurebot completely

10:03 hmm

10:05 ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly {}))

10:05 clojurebot: {}

10:06 Chousuke: (alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form))))

10:06 ,(alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form))))

10:06 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--2954$fn

10:06 liwp: Did you just disable all sandboxing from clojurebot?

10:06 Chousuke: no

10:06 I'm trying to fix it

10:07 the sandboxing was alredy disabled :P

10:07 ,1

10:07 clojurebot: 1

10:07 liwp: I mean the (constantly {}) bit

10:07 fair enough ;)

10:07 Chousuke: ,(alter-var-root #'hiredman.sandbox/de-fang (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form)))

10:07 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--2966$fn

10:07 Chousuke: gah

10:07 the defang function is too complex

10:08 ,(alter-var-root #'hiredman.sandbox/de-fang (constantly (fn [form notallowed] (if (list? form) (when (not (some notallowed (tree-seq seq? #(let [a (macroexpand %)] (or (and (seq? a) a) (list a))) form))) form) form))))

10:08 clojurebot: #<sandbox$eval__2978$fn__2980 sandbox$eval__2978$fn__2980@ca1465>

10:08 liwp: don't you need an extra layer of fn in that, because alter-var-root takes and fn that is applied to the var?

10:08 Chousuke: okay, now the defang thingy should be working

10:08 liwp: exactly

10:09 so what does it do exactly?

10:09 filters out bad forms?

10:09 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* assoc 'this-is-a-test)

10:09 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$assoc

10:09 liwp: one more arg

10:10 Chousuke: gah, it was a set originally...

10:10 liwp: heh

10:10 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'this-is-a-test}))

10:10 clojurebot: #{this-is-a-test}

10:10 Chousuke: ,this-is-a-test

10:10 clojurebot: java.lang.Exception: Unable to resolve symbol: this-is-a-test in this context

10:10 Chousuke: hmm.

10:11 ,eval

10:11 clojurebot: #<core$eval__5182 clojure.core$eval__5182@4d8040>

10:11 Chousuke: *sigh*

10:11 maybe I should just give up

10:12 liwp: can you rebind alter-root-var and thereby plug the hole?

10:12 for the time being

10:12 Chousuke: that might break other things though

10:12 liwp: OTOH the bot is broken in any case so you can't really make things worse that way...?

10:13 Chousuke: ,(eval '5)

10:13 liwp: it's gone to bed?

10:13 clojurebot: 5

10:14 Chousuke: nope :(

10:14 ,(this-is-a-test '5)

10:14 clojurebot: DENIED

10:14 Chousuke: ooh

10:14 okay, now I can perhaps fix it

10:14 liwp: so now you need to add all the bad forms to your set

10:15 maybe remove your this-is-a-test as well ;)

10:15 Chousuke: ,(alter-var-root #'hiredman.sanbox/*bad-forms* (constantly #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot}))

10:15 clojurebot: Chousuke: Excuse me?

10:15 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot}))

10:15 clojurebot: Chousuke: Huh?

10:15 Chousuke: garr

10:16 liwp: ,(this-is-a-test '0)

10:16 clojurebot: DENIED

10:17 liwp: ,(+ 1 1)

10:17 clojurebot: 2

10:17 Chousuke: ,(var-set #'hiredman.sandbox/*bad-forms* #{'intern 'eval 'def 'catch 'load-string 'load-reader 'clojure.core/addMethod 'hiredman.clojurebot/bot})

10:17 clojurebot: Chousuke: excusez-moi

10:18 liwp: I've never looked at the bot source, but it looks like that's not ever getting to the evaluator

10:19 Chousuke: fortunately the channel is rather quiet at the moment :P

10:19 other than this bot-trickery

10:22 ,(var-set #'hiredman.sandbox/*bad-forms* '#{intern eval def catch load-string load-reader clojure.core/addMethod hiredman.clojurebot/bot})

10:22 clojurebot: Chousuke: Pardon?

10:22 Chousuke: :(

10:22 liwp: ,(var-set + +)

10:22 clojurebot: java.lang.ClassCastException: clojure.core$_PLUS___4443 cannot be cast to clojure.lang.Var

10:23 liwp: ,(var-set #'+ #'+)

10:23 clojurebot: java.lang.IllegalStateException: Can't change/establish root binding of: + with set

10:23 Chousuke: I wonder if the set thing is confusing it.

10:23 liwp: good

10:23 try using set

10:23 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms conj 'catch)

10:23 clojurebot: Chousuke: Titim gan éirí ort.

10:24 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'catch)

10:24 clojurebot: Chousuke: Huh?

10:24 liwp: I don't think it likes you

10:24 Chousuke: heh

10:24 rsynnott: Why does the bot speak Irish?

10:25 liwp: rsynnott: it's a polyglot, it speaks french as well

10:25 Chousuke: ,#=(alter-var-root #=(var hiredman.sandbox/*bad-forms*) conj catch)

10:25 clojurebot: Chousuke: Titim gan éirí ort.

10:25 liwp: Chousuke: since you're messing with the both, you might as well add finnish error messages

10:25 Chousuke: ,#'hiredman.sandbox/*bad-forms*

10:25 clojurebot: #'hiredman.sandbox/*bad-forms*

10:26 rsynnott: Particularly unusual language for evil robots, though :)

10:26 Chousuke: ??? I'm confused

10:26 liwp: Chousuke: aren't you getting the args in the wrong order with conj here, i.e. it'll become (conj foo #{})

10:26 Chousuke: liwp: it's an altering function so it'll pass the thing to be altered as the first parameter

10:26 liwp: ok

10:26 Chousuke: and any user-supplied args after that

10:27 but it seems it's even more broken now.

10:27 liwp: ,(#'hiredman.sandbox/*bad-forms* 'this-is-a-test)

10:27 clojurebot: DENIED

10:28 liwp: ,this-is-a-test

10:28 clojurebot: java.lang.Exception: Unable to resolve symbol: this-is-a-test in this context

10:28 liwp: ,'this-is-a-test

10:28 clojurebot: this-is-a-test

10:28 liwp: duh

10:35 Chousuke: ah, now I know why it doesn't like me

10:35 ,catch

10:35 clojurebot: Chousuke: It's greek to me.

10:36 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* (constantly #{'intern 'eval 'def 'load-string 'load-reader 'clojure.core/addMethod}))

10:36 clojurebot: #{intern load-reader load-string clojure.core/addMethod eval def}

10:36 Chousuke: ~def alter-var-root

10:37 ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alterRoot

10:37 clojurebot: EOF while reading

10:37 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alterRoot)

10:37 clojurebot: #{alterRoot intern load-reader load-string clojure.core/addMethod eval def}

10:37 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj 'alter-var-root)

10:37 clojurebot: #{alterRoot intern load-reader load-string clojure.core/addMethod eval alter-var-root def}

10:37 Chousuke: ,(alter-var-root #'hiredman.sandbox/*bad-forms* conj :test)

10:37 clojurebot: DENIED

10:37 Chousuke: ,(.alterRoot #'hiredman.sandbox/*bad-forms* conj :test)

10:37 clojurebot: DENIED

10:38 Chousuke: excellent

10:42 avital: Hello Chous{er,uke} and friends. It seems that pr is supposed to print a value in the exact way the reader can read it. But (pr '(1)) prints (1) instead of '(1). Is this a bug?

10:42 ,(pr '(1))

10:42 clojurebot: (1)

10:44 Chousuke: avital: it's not a bug. pr is a function, so its parameter is evaluated

10:44 and if you read "(1)", you indeed get '(1)

10:44 ,(read-string "(1)"

10:44 clojurebot: EOF while reading

10:44 Chousuke: ,(read-string "(1)")

10:44 clojurebot: (1)

10:45 Chousuke: ,(read-string "'(1)")

10:45 clojurebot: (quote (1))

10:54 liwp: Chousuke: good job with the bot

10:55 Chousuke: yes. first I break it and then I fix it :P

10:55 all publicly on IRC

10:55 Fossi: that's the spirit

10:55 liwp: you should've PM'd it

10:55 in the privacy of your own irc client

10:56 Chousuke: I don't know if it listens to PMs :/

10:56 Fossi: it does

10:56 liwp: it does

10:56 Fossi: it's more fun in public though :D

10:56 liwp: so what was wrong with (alter-var-root #'hiredman.sandbox/*bad-forms* conj 'catch)?

10:57 Chousuke: liwp: it turned out that an earlier function tests whether the message string contains "catch". :P

10:57 liwp: auts

11:35 adityo: ola guys!

11:36 how do i remove a key/value pair from a map ..say {"lisp" "mcarthy", "Clojure" "Hickey"} and i want to remove lisp/mcarthy

11:37 stuartsierra: (dissoc *the-map* "lisp")

11:39 adityo: cool, was thinking of writing somethings in the line of remove-if in CL

11:41 thanks

11:42 stuartsierra: np

11:52 chouser: hiredman: thanks for mentioning "Evolution of Lisp". It's fascinating.

11:52 "This situation of unexpected performance is prevalent with Lisp."

12:09 ambient: one thing that really bothers me about functional programming and immutability is the performance issue

12:10 but that's not such a huge thing because of the versatility. python is about 60 times slower than C. people (and I) still use it because it gets things done a lot faster

12:12 stuartsierra: With any language, you write the code you want, then optimize a few critical sections, often by rewriting in another language. Clojure->Java, Java->C, C->assembly

12:14 ambient: i'd rather just use one language :/ but perhaps that's a pipe dream if i want both dynamicality(?) and performance

12:14 chouser: ambient: keep the dream alive

12:15 stuartsierra: Write a better compiler. Or a better VM.

12:15 It happens, just slowly. Almost no one writes assembly any more; C compilers are good enough.

12:16 Java is getting there.

12:16 chouser: falling back to mutable structures (like arrays) and sufficient use of macros (and other possible features like reify) we can hope to get *very* close to java speed while retaining many of clojure's abstractions, even in the small pieces of code where performance is most critical.

12:46 tmountain: as far as VM are concerned, hotspot is actually one of the best IMO

12:54 konr: Isn't there a version of (binding) that creates the variables, if they don't exist?

12:54 technomancy: (doc with-local-vars)

12:55 Chousuke: I haven't found much use for local vars :/

12:56 technomancy: yeah, it seems like the wrong answer

12:57 stuartsierra: konr: the variables still have to be (declare ...)'d if you want to use them in other functions.

13:03 technomancy: stuartsierra: I'm looking at your swank-clojure changes

13:03 I'm not really understanding the clojure-maven-plugin

13:03 why does it take eleven Java classes just to perform clojure compilation?

13:04 stuartsierra: It doesn't.

13:04 clojure-maven-plugin does a bunch of different things -- compile source, compile tests, run main, run tests, run repl, run swank, generate docs...

13:05 Each "goal" in Maven-speak needs its own class

13:06 technomancy: ok, that's more than I've been using maven for so far.

13:06 stuartsierra: Most of them are small classes that call the methods in AbstractClojureCompilerMojo

13:07 technomancy: it would be nice if this stuff didn't have to be written in Java, but I've had a nasty time trying to gen-class maven stuff due to the wackiness in its classpath

13:08 *class loader

13:08 stuartsierra: It could be done, but then clojure-maven-plugin would have a dependency on Clojure, which is almost circular.

13:09 Mostly the plugin just invokes clojure.main with different arguments.

13:09 technomancy: as long as I'm not the one writing / reading it

13:09 can't you do that from the pom though?

13:09 stuartsierra: technomancy: not really, and not conveniently.

13:09 technomancy: we do that at work; seems a lot simpler

13:09 for AOT and test running

13:10 stuartsierra: The point of Maven plugins is to keep the POM simple and declarative, not full of the procedural-type scripting one does with Ant.

13:11 technomancy: ok, I'll try this out

13:11 stuartsierra: The plugin code really isn't that bad; I was able to add the SWANK stuff without knowing much about Maven internals.

13:11 technomancy: cool

13:11 did you say something about wanting to start a repo for OSS clojure projects?

13:12 stuartsierra: It was a half-formed idea to set up a Maven repo and encourage Clojure library developers to use it.

13:12 technomancy: sounds good to me

13:12 stuartsierra: First I think we need to get swank-clojure and clojure-maven-plugin 1.1 into central.

13:13 technomancy: once clojure 1.1 is out?

13:13 stuartsierra: Not necessarily.

13:13 Then we need a Maven archetype for new Clojure projects, and get THAT into central.

13:13 technomancy: you'd need a VPS or something to allow each contributor to have a user account, right?

13:13 so they can push out releases

13:14 stuartsierra: Dunno; I'm not that familiar with Maven deployment setups.

13:15 technomancy: I guess you could accept pubkeys from contributors all hooked up to the same user as long as you trust them

13:15 stuartsierra: Basically, I want to lower the barrier to creating & releasing Maven-enabled Clojure libraries, so that everyone does it.

13:15 technomancy: yes

13:16 stuartsierra: So my plan of attack is 1. SWANK, 2. plugin, 3. archetype, 4. repository.

13:19 technomancy: I feel a little uneasy that jochu has a "start server refactoring" commit on the master branch with no further commits referencing it. =\

13:19 yeesh; the centralized repos are slow.

13:20 stuartsierra: you might want to ask jochu about that; maybe he has an older version that's stable enough for a 1.0

13:21 konr: Isn't it awesome? Clojure is even more concise than CL: http://scorciapino.com/pub/fotos/clj-vs-cl.png

13:23 stuartsierra: On a related note, does the swank server target a particular version of SLIME? It would be nice to have that documented somewhere.

13:23 technomancy: stuartsierra: slime doesn't really have versions

13:23 well... no, it has 1.0, and that's it

13:23 I think they've decided they don't do "releases"

13:24 stuartsierra: charming

13:24 technomancy: basically I have a fork of slime, and I set M-x clojure-install to use my fork, and I only update it when I've confirmed it works.

13:25 stuartsierra: Ok. What if SLIME were packaged with swank-clojure?

13:25 technomancy: that's actually not a bad idea

13:25 since it's just a single .el file

13:25 actually, that's a great idea

13:26 most of the code in slime is CL that's irrelevant anyway

13:26 I was thinking about asking if they wanted to merge swank-clojure into slime, but I don't think that would ever happen

13:26 why not go the other way...

13:27 Raynes: technomancy's brain is about to explode.

13:27 stuartsierra: Emacs couldn't load the .el code from a Maven JAR, but you could still tell Clojure users to get SLIME from the swank-clojure zip/tar distribution.

13:28 technomancy: stuartsierra: well swank-clojure already bundles a .el file anyway

13:28 stuartsierra: Right.

13:28 So it should be easy enough.

13:29 technomancy: clojure-maven-plugin failed after twenty minutes of downloading asking for a gpg passphrase. =\

13:29 stuartsierra: Hit enter.

13:29 technomancy: right; that made it fail

13:29 stuartsierra: weird, haven't had that problem

13:29 technomancy: gpg: no default secret key: secret key not available

13:30 I guess I need to generate one

13:30 I just want to install it though. =\

13:30 * technomancy comments out maven-gpg-plugin

13:30 technomancy: there we go

13:30 this is why we need this in a centralized repo somewhere

13:31 stuartsierra: Or comment out the key-signing stuff in the clojure-maven-plugin POM

13:31 I think you only need that to publish releases in central.

13:32 technomancy: bug filed

13:34 stuartsierra: is there a way to see what goals are defined?

13:34 like rake -T ?

13:36 stuartsierra: For a single plugin, yes: "mvn help:describe"

13:36 For all plugins, no.

13:36 mvn help:describe -DgroupId=com.theoryinpractise -DartifactId=clojure-maven-plugin -Dversion=1.1-SNAPSHOT

13:36 sproingie: what a horrible horrible ui

13:36 in a sane world that might be "mvn-help -p clojure"

13:37 technomancy: don't forget the -o "don't download the Internet again" argument. =\

13:38 sproingie: worst thing it would do is download the plugin itself which tends to be small

13:38 stuartsierra: It never downloads the internet again.

13:40 technomancy: hmm... I can't get any of these goals to run

13:40 sproingie: might have to be mvn-help -g com.theoryinpractise -p clojure

13:40 technomancy: I'll have to come back to this later

13:40 stuartsierra: ok

13:40 sproingie: but maven seems to have some way of figuring out groupIds of plugins automagically

13:41 probably some kind of index on <x>-maven-plugin

13:41 stuartsierra: if they're built-in or defined in the <plugins> section of your current project, it's just "mvn help:describe -Dcmd=clojure:..."

13:41 sproingie: that's exactly what it does

13:42 LauJensen: stuartsierra, did you sort out file posting in your http agent yet ?

13:42 stuartsierra: no

13:42 I seriously doubt I'm going to.

13:42 LauJensen: oh, why the change of heart ?

13:43 stuartsierra: I looked at what it entails. There's Base64 encoding, MIME headers, etc.

13:43 * sproingie read that as "what it entrails"

13:43 stuartsierra: The Apache HTTP library handles that well already. I'm not going to reimplement it.

13:43 LauJensen: Softened your knees a little bit, did it? :)

13:43 stuartsierra: exactly.

13:43 LauJensen: It's fine, apache libs work without problems anyway

13:44 stuartsierra: maybe someday I'll rewrite HTTP agent based on Apache's client, but I've got bigger fish to fry right now.

13:45 LauJensen: Alright

13:45 technomancy: that'd have to wait till Dependencies Work anyway

13:45 stuartsierra: truth, hence my recent enthusiasm for Maven

13:46 LauJensen: Are you guys working on something with Maven ?

13:49 stuartsierra: (1:16:42 PM) stuartsierra: Basically, I want to lower the barrier to creating & releasing Maven-enabled Clojure libraries, so that everyone does it.

13:49 (1:16:47 PM) technomancy: yes

13:49 (1:17:37 PM) stuartsierra: So my plan of attack is 1. SWANK, 2. plugin, 3. archetype, 4. repository.

13:53 ambient: reading through clojure.core this sentence really took a long time to parse :P "Evaluates exprs one at a time, from left to right. If a form returns a logical true value, or returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expression. (or) returns nil."

13:55 hircus: I think parenthesizing or quoting the first "or" would help readability a lot

13:57 LauJensen: stuartsierra, thanks, I'm awake now

13:57 Let me know when you have something we should try out

13:58 stuartsierra: You can try the latest from github: http://github.com/jochu/swank-clojure and http://github.com/talios/clojure-maven-plugin

14:01 LauJensen: I'll have a look

14:04 stuartsierra, looks like you're filling a void in clojure-land, weee :)

14:04 liwp`: ~library

14:04 stuartsierra: falling into the void, more like

14:05 liwp`: huh, where's clojurebot? did hiredman take it off-line for patching?

14:27 LauJensen: liwp, yea he's probably in the shop :) Chousuke messed him up a little bit

14:28 liwp or actually looking through my log, its possible he just didn't recover from the ircd's restart

14:28 Chousuke: LauJensen: clojurebot already returned ;P

14:29 though now I have to fix him again

14:29 LauJensen: Chousuke, so you're saying, check the user list before analyzing logs? :)

14:29 hiredman: I did nae restart it, just had it reconnect and rejoin

14:29 Chousuke: or hm, I suppose the process itself survivved.

14:30 ,(alter-var-root error)

14:30 clojurebot: DENIED

14:30 Chousuke: -v

14:40 dnolen: cgrand: been thinking a little bit about enlive again, specifically nesting template/snippets. You said this would be slow. Would it make sense to cache the fast representation to disk?

14:40 cgrand: dnolen: I saw you forked it again :-)

14:41 I don't remember what was your use case.

14:42 dnolen: just dynamically selecting sub templates from a template.

14:42 template inheritance is what I wanted i realize.

14:43 * cgrand digging through its mail archives

14:46 dnolen: cgrand: http://groups.google.com/group/clojure/msg/4469f364b0b7c09f

14:46 this was your response

14:48 cgrand: dnolen: thx

14:51 there are two things that makes a dynamic snippet like the one in your sample code slow: parsing and pre-serializing. Parsing overhead is easily worked around by loading your html once.

14:51 dnolen: cgrand: does it make sense to cache the parsed content to disk?

14:53 cgrand: dnolen: I don't think

14:53 wooby: hello, would anyone happen to know why this gives me 'malformed member expression?' (.. os write (to-byte-array file) 0 (.. file length))

14:53 dnolen: cgrand: k, what do you mean by pre-serializing?

14:56 liwp`: wooby: (..file lenght) seems broken to me

14:56 you should avoid the .. forms if you can

14:56 use -> instead

14:56 wooby: ah, does that do the same thing?

14:57 liwp`: in effect yes

14:57 so something like (-> os write (to-byte-array...))

14:57 kotarak: But it also allows for clojure functions and macros... (-> x .methodCall clj-fun (a-macro with other args))

14:58 cgrand: dnole; once a html tree is loaded, each node is annotated with its serialization. Hence when Enlive serilaizes the output of a transformation, if a node is untouched by the transformation it can skip walking it and directly emits the cached serialization.

14:58 dnolen: that's for you ^^

14:58 wooby: i see... thank you

14:58 liwp`: wooby: the 0 in the middle of your .. form looks suspect as well

14:59 wooby: liwp: what i'm trying to do is write a file's contents to a socket's output stream

14:59 liwp`: are you trying to call write on os and everything else is just a set of arguments to the write call?

14:59 wooby: it's entirely possible i'm going about it entirely the wrong way

14:59 correct

14:59 dnolen: cgrand: i see. so how would you handle template inheritance using Enlive? :)

15:00 liwp`: wooby: you should have something like (.write os <args>)

15:00 wooby: http://gist.github.com/203318 that's the whole thing so far... forgive the style, i'm sure it sucks

15:00 but i appreciate any and all feedback

15:00 liwp`: let's see: (.write os (to-byte-array file) 0 (.length file))

15:00 try that

15:00 cgrand: dnolen: could you be more specific on what you call template inheritance?

15:01 liwp`: wooby: so whenever you want to call a method you should use (.method object)

15:01 except for static methods it would be (Class/method ...)

15:02 wooby: I see a lot of .. forms in your code and most of them are wrong, e.g. (.. sock close) should be (.close sock)

15:02 cgrand: but this annotation phase can be moved out of snippet* and put into html-resource, this would make dynamic snippets lighter

15:02 liwp`: wooby: I guess the .. form works as well, but it's not idiomatic

15:02 wooby: ok thanks, it's what i'm aiming for

15:02 just going off the book so far

15:03 ambient: it looks like a lot of .java in clojure/src/jvm is machine generated?

15:03 liwp`: ambient: nope

15:03 ambient: huh, weird

15:03 liwp`: or possibly some of the invoke defs

15:04 dnolen: cgrand: for example, 3 column layout. that's one template. then I have a nav template. In one app I'd like to put this in column 1 in the base 3 column template. Nav template supports showing different widgets. Each widget is itself a template.

15:05 liwp`: wooby: in the past people used to write (.. my-obj meth1 meth2 meth3), (. my-obj method) and (new Foo). These days the fashion is to write (-> my-obj m1 m2 m3) (.method my-obj) and (Foo.) instead

15:06 cgrand: dnolen: have to go, can we continue by mail? Can't you achieve what you describe by function composition?

15:06 liwp`: wooby: the (.. os...) form seems to be the only broken bit in the gist (haven't tried running it)

15:06 wooby: liwp: got it, thank you

15:06 kotarak: cgrand, dnolen: would keep also informed?

15:06 I'm also interested in this!

15:07 wooby: liwp: thanks, i managed to fix it thanks to your help, now working on another bug

15:07 Chousuke: the .. form is still fine sometimes though.

15:07 dnolen: cgrand: you're probably right, I've just started thinking about this again.

15:07 Chousuke: you can't access statics through -> IIRC.

15:07 or hm

15:07 ,(-> Math .PI)

15:07 clojurebot: java.lang.IllegalArgumentException: No matching field found: PI for class java.lang.Class

15:07 Chousuke: right.

15:07 kotarak: Chousuke: ,(-> Math/PI)

15:07 ,(-> Math/PI)

15:07 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$--GT-

15:08 kotarak: ,(-> Math/PI identity)

15:08 clojurebot: 3.141592653589793

15:08 Chousuke: kotarak: yeah, but that won't work if it's nested somehow... on second thought, is that even possible? :P

15:08 kotarak: nested?

15:08 Chousuke: never mind. I don't think it's possible :)

15:09 kotarak: I don't understand the nested.

15:09 raek: my first library: http://github.com/raek/clojure-sandbox/blob/master/src/com/github/raek/xml_with_xmlns.clj

15:09 Chousuke: I mean (-> foo .bar .static ...)

15:09 raek: extending clojure.xml with xml namespaces

15:09 kotarak: Chousuke: You mean .bar returns a class, which you want to use as part in front of the "/"?

15:10 liwp`: Chousuke: shouldn't that just work, i.e. can't you just call the static method on the instance rather then the class?

15:10 Chousuke: liwp`: yeah, I guess you can

15:11 raek: {:tag :foo:bar :attrs {:xmlns:foo "http://example.com/ns"}} => {:tag :http://example.com/ns/bar :attrs {}}

15:12 kotarak: ,(-> "123" Integer/valueOf (.valueOf "567"))

15:12 clojurebot: java.lang.IllegalArgumentException: No matching method found: valueOf for class java.lang.Integer

15:15 liwp`: kotarak: so you can't call a static method on an instance...

15:15 chouser: uh

15:15 kotarak: liwp`: It seems like this is not possible, no. Any Java gurus around?

15:15 raek: (anyone here using clojure.xml and/or xml namespaces?)

15:16 crios: in Java you can call a static methond on an instance

15:16 wooby: sweet, this little webserver totally works now... thanks everyone for your help

15:16 http://gist.github.com/203329

15:17 kotarak: ,(.valueOf 5 "123")

15:17 clojurebot: java.lang.IllegalArgumentException: No matching method found: valueOf for class java.lang.Integer

15:17 kotarak: hmmm

15:17 liwp`: kotarak: in java you're definitely allowed to write Foo f = new Foo(); f.staticMethod();

15:17 it's not good style, but it's allowed

15:17 kotarak: I believe you. But it obviously doesn't work in Clojure.

15:17 liwp`: yep

15:19 mgarriss: (n00b warning) why does this: http://pastie.org/644262 produce this error: "java.lang.IllegalArgumentException: recur arg for primitive local: x must be matching primitive"

15:21 kotarak: mgarriss: Math/pow is double, while (/ x y) is maybe integer? (Just guessing)

15:22 chouser: pow returns a primitive double. / will only return a primitive double if both x and y are also

15:23 So (double (/ x y)) or (/ (double x) (double y))

15:23 kotarak: The code is (/ x 10). So maybe (/ x 10.0)?

15:23 raek: anyway, if you are interested in taking a look at a newbie's code: http://github.com/raek/clojure-sandbox/blob/master/src/com/github/raek/xml_with_xmlns.clj

15:24 all kinds of comments are welcomed

15:25 mgarriss: hmm, the (/ x 10.0) didn't work

15:25 kotarak: mgarriss: try chouser's tip

15:26 mgarriss: that was it!

15:26 Chousuke: (/ x (double 10)) should be enough, since x is already double

15:26 mgarriss: thx all

15:26 chouser: Chousuke: yep, hadn't read the paste yet. :-{

15:26 er, :-P

15:29 mgarriss: i guess i'm not clear as to why i needed to do that

15:30 liwp`: ,(class (/ 10 2))

15:30 clojurebot: java.lang.Integer

15:30 liwp`: ,(class (/ 10 2.0))

15:30 clojurebot: java.lang.Double

15:30 chouser: mgarriss: when you create a local (via let or loop), if the value assigned to it will be a primitive, the local itself will be a primitive.

15:30 mgarriss: but shouldn't have x already been a double?

15:30 chouser: yes, x was indeed a primitive double.

15:31 so the problem was the recur, where you were trying to assign the result of (/ x 10) back to x

15:32 numeric literals in Clojure are boxed, so / sees a primitive double (x) and a instance of Integer (10)

15:32 mgarriss: boxed?

15:32 chouser: that causes / to compile to a form that would return a Number

15:33 boxed means non-primitive -- an instance of a Class that extends Object vs. a primitive which isn't an instance of any class type, it's a special built-in Java primitive.

15:34 mgarriss: this is all in an attempt to learn some more clojure and to prove this: http://en.wikipedia.org/wiki/Kaprekar_constant

15:35 i love clojure already, ruby is paying the bills but driving me nuts

15:37 crios: a "boxed" object lives in the "heap" memory, and it is garbage collected. A primitive datum lives in the stack

15:37 hoeck1: mgarriss: mhh, strange, it disappears when wrapping the first recur form in a double: (recur (double (/ x 10)) ....)

15:38 crios: and it is not collected

15:38 chouser: so (double (/ x 10)) or (/ x (double 10)) should work.

15:39 mgarriss: chouser: i used the former

15:39 chouser: you can experiment with repl-utils/expression-info to see details about the return types including (primitive or not) of expressions.

15:39 mgarriss: the latter probably has slightly better performance, if that matters.

15:39 mgarriss: it does, i was just about to ask about that

15:40 chouser: (double (/ x 10)) will box the x, do the math, return a Double (boxed), and then unbox it to a double

15:41 (/ x (double 10)) will use an unboxed 10, do primitive math on it and use the result directly.

15:41 mgarriss: new version (i also had to subtract 1 from number of digits): http://pastie.org/644313

15:41 Chousuke: I think (dec x) is more idiomatic than (- x 1)

15:42 mgarriss: good call

15:42 is dec more efficient then (- x 1) ?

15:42 i imagine it is

15:43 chouser: probably.

15:43 Chousuke: ~def dec

15:43 mgarriss: it's certainly easier to read

15:43 chouser: you should test any performance claims, as the JVM can do unexpected magic (or fail to perform expected magic)

15:43 Chousuke: well, apparently it uses some java magic... so maybe

15:44 chouser: but having said that, it looks like (double 10) may be unboxing that Integer every time.

15:45 you might try (def digits (let [ten (double 10)] (fn [number] ... (/ x ten) ...)))

15:46 crios: so the unbox occurs just one time?

15:48 chouser: right. the closure stored in digits would then close over the primitive 'ten' which would be used in the loop. Surely the JVM can perform magic on that. :-)

15:48 but again, you'd have to test on a fully warmed-up JVM to be sure

15:49 spuz: I'm having a bit of a weird problem with a method on a class not being found. Is there a way to enumerate all of the instance and static methods on a class from clojure?

15:49 herdrick: Hi. I'm wanting to use union and intersection for Maps (hashes).

15:50 chouser: spuz: try clojure.contrib.repl-utils/show

15:50 technomancy: spuz: in slime it's C-c I

15:50 herdrick: It looks like I can use clojure.set.project to make something that works like this but it's ugly

15:50 technomancy: or use repl-utils

15:50 herdrick: Like this:

15:50 (project [map1 map2] (intersection (set (keys map1)) (set (keys map2))))

15:50 mgarriss: ugh, now i need an undigits that undoes digits

15:53 hiredman: I was just reading a pdf that discussed the chaotic nature of performance on today's platforms

15:56 crios: maybe too many layers

15:57 hiredman: well, you get chaotic (extremely sensitive to initial conditions) performance behaviour from cpus even, but I'm sure the jvm's optimizing (or not) doesn't help

15:58 herdrick: part of the problem is that what I want isn't really just an intersection of the keys of the maps,

15:59 but rather new maps of a subset of each original map

15:59 clojurebot: new Class(x) is (Class. x)

16:01 herdrick: sorry: new maps, each a subset of one of the original maps,

16:01 using the keys found in both

16:04 crios: cloning the values of those keys?

16:06 kotarak: herdrick: this are probably not well-defined operations. What happens in this case: (hypothetical-map-union {:a 2 :b 3} {:b 4 :c 5})?

16:07 mgarriss: undigits was much easier: (defn undigits [numbers] (reduce + (map #(* %2 %) powers-of-10 (reverse numbers))))

16:08 chouser: could use * instead of #(* %2 %)

16:08 kotarak: herdrick: union is merge, btw. intersection can probably be done with select-keys.

16:08 herdrick: kotarak: sorry, i think my irc client is doing something funny with your code. What's the second key of your second Map?

16:09 kotarak: herdrick: colon c (or (keyword "c"))

16:09 ,(merge {:a 2 :b 3} {:b 4 :c 5})

16:09 clojurebot: {:c 5, :a 2, :b 4}

16:09 herdrick: Also, yes, map-union would need to be like merge or merge-into

16:09 kotarak: ,(select-keys {:a 2 :b 3} [:b])

16:09 clojurebot: {:b 3}

16:10 kotarak: (where [:b] is the intersection of the keys of the two maps)

16:11 ,(let [m1 {:a 2 :b 3} m2 {:b 3 :c 4}] (select-keys m1 (clojure.set/intersection (set (keys m1)) (set (keys m2)))))

16:11 clojurebot: {:b 3}

16:12 mgarriss: chouser: good call, not sure what i was thinking there

16:14 herdrick: kotarak: but you are only preserving the values for m1 there

16:15 kotarak: i want both

16:15 crios: ,(class (seq []))

16:15 clojurebot: nil

16:15 kotarak: herdrick: that's where the "not well-defined" comes into play.

16:15 herdrick: kotarak: the code I pasted in above does that

16:15 crios: Why is it nil? Shouldnt'it be an empty sequence?

16:15 herdrick: here it is again:

16:15 (project [map1 map2] (intersection (set (keys map1)) (set (keys map2))))

16:15 chouser: crios: seq on an empty collection returns nil

16:15 hiredman: crios: what does (seq []) return?

16:16 herdrick: kotarak: well, it only takes a careful definition... :)

16:16 but thanks,

16:16 kotarak: herdrick: then it's not "intersection" of maps

16:16 herdrick: your code must return something different

16:16 herdrick: right, it returns two maps

16:16 crios: seq [] returns null, mm thank you

16:17 herdrick: so it isn't really an intersection

16:17 it

16:17 it's something else

16:17 BTW I just used clojure.set/project because it seems to do what I wanted but I don't really understand the short description of it

16:18 kotarak: ,(let [m1 {:a 2 :b 3} m2 {:b 3 4} intersected-keys (clojure.set/intersection (set (keys m1)) (set (keys m2)))] (vector (select-keys m1 intersected-keys) (select-keys m2 intersected-keys)))

16:18 clojurebot: 3

16:19 kotarak: ,(let [m1 {:a 2 :b 3} m2 {:b 3 :d 4} intersected-keys (clojure.set/intersection (set (keys m1)) (set (keys m2)))] (vector (select-keys m1 intersected-keys) (select-keys m2 intersected-keys)))

16:19 clojurebot: [{:b 3} {:b 3}]

16:22 herdrick: ,(let [m1 {:a 1 :b 2} m2 {:b 3 :c 4}] (clojure.set/project [m1 m2] (clojure.set/intersection (set (keys m1)) (set (keys m2)))))

16:22 clojurebot: #{{:b 2} {:b 3}}

16:22 herdrick: kotarak: that's the way i was doing it

16:23 kotarak: herdrick: well, ... when it works. :) It's shorter.

16:23 herdrick: kotarak: but your way is possibly superior

16:23 kotarak: thanks for the help

16:23 kotarak: herdrick: maybe, maybe not. But it's good to know select-keys :)

16:24 herdrick: kotarak: it sounds like you know more about sets in Clojure than me. Can you tell me about clojure.set/project ?

16:24 I don't get what xrel is in the docs

16:24 kotarak: herdrick: oehm... actually never used it :P

16:24 Let's see.

16:24 (doc clojure.set/project)

16:24 clojurebot: "([xrel ks]); Returns a rel of the elements of xrel with only the keys in ks"

16:24 herdrick: kotarak: me neither until now

16:25 kotarak: Just watching Joshua Bloch's "How to Design a Good API and Why it matters": don't use cryptic abreviations....

16:26 herdrick: kotarak: indeed

16:28 kotarak: Well. It simply maps select-keys over the xrel part.

16:28 And turns the result again into set. (Which might not be what you want.)

16:28 ,(let [m1 {:a 1 :b 2} m2 {:b 2 :d 4}] (clojure.set/project [m1 m2] (clojure.set/intersection (set (keys m1)) (set (keys m2)))))

16:28 clojurebot: #{{:b 2}}

16:28 herdrick: kotarak: yeah, except for the "turns the result again into set" part

16:29 kotarak: that breaks my code when the two new maps are the same

16:29 kotarak: exactly

16:29 herdrick: kotarak: exactlt!

16:29 sorry, exactly!

16:29 lol

16:29 kotarak: i'm going with your version

16:29 kotarak:thanks

16:30 kotarak: herdrick: np

16:37 mgarriss: how do i combine 2 vectors into one?

16:38 chouser: ,(into [1 2 3] [4 5 6])

16:38 clojurebot: [1 2 3 4 5 6]

16:38 mgarriss: thx

16:39 hircus: ,(reduce conj [1 2 3] [4 5 6])

16:39 clojurebot: [1 2 3 4 5 6]

16:39 mgarriss: how do i create a vector of some given size containing all zeroes?

16:39 clojurebot: with style and grace

16:40 chouser: into should use transients while reduce conj I think would not.

16:40 mgarriss: i don't really understand the reduce method

16:40 chouser: ,(vec (repeat 12 0))

16:40 clojurebot: [0 0 0 0 0 0 0 0 0 0 0 0]

16:41 hircus: for each element in the second sequence, it applies conj to the first sequence and that element, and then repeats with the resulting sequence and the rest of the second sequence

16:41 ,(doc reduce)

16:41 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the r

16:42 mgarriss: i see, very cool

16:42 hircus: mgarriss: this is probably a more obvious example: ,(reduce * [1 2 3])

16:42 ,(reduce * [1 2 3])

16:42 clojurebot: 6

16:42 kotarak: hilarious : http://www.youtube.com/watch?v=aAb7hSCtvGw#46m0s

16:43 rather http://www.youtube.com/watch?v=aAb7hSCtvGw#t=46m0s

16:43 hiredman: clojurebot: botsnack

16:43 clojurebot: thanks; that was delicious. (nom nom nom)

16:44 hircus: or defining factorial this way

16:44 ,(reduce * (take 5 (iterate inc 1)))

16:44 clojurebot: 120

16:49 mgarriss: i can see myself using reduce a lot in the future

17:13 rosejn: What's the best way to look at *err* while in the repl?

17:14 tomoj: rosejn: I'm not sure that makes sense

17:14 rosejn: hmmm, ok

17:14 ambient: *e

17:14 tomoj: oh, now I get it. been awake too long. :(

17:14 ambient: ?

17:14 rosejn: I'm trying to use clojure.contrib.logging

17:14 ambient: (i dont even know what *err* does)

17:15 tomoj: it's STDERR, no?

17:15 rosejn: It's just like another standard out, but for errors

17:15 ambient: ok

17:15 rosejn: a pipe you can connect to things

17:15 tomoj: you mean the slime repl or a plain old repl?

17:15 rosejn: vimclojure repl

17:16 I've inserted (log :debug "my msg here...") messages, but it seems that clojure.contrib.logging is sending stuff to *err*

17:17 it's also not clear how to set the log-level...

17:17 tomoj: I suppose that's vimclojure's business, not clojure's? (the former)

17:17 mgarriss: i need a function that returns any repeating pattern in a vector: (foobar [3 4 19 2 4 2 4 2 4 2]) ==> [2 4]

17:17 or i should say the first repeating pattern found

17:18 lisppaste8: crios pasted "ternary if" at http://paste.lisp.org/display/88306

17:19 crios: sure do exits a better way than my "ternary if" in http://paste.lisp.org/display/88306

17:19 *exists

17:19 chouser: crios: you want :else ?

17:20 crios: mmm I think so. but can I put an if inside cond?

17:21 BTW, why (memq 'n '(a b c) ) throw a StackOverflowException?

17:21 hiredman: cond checks for true values

17:22 not nil and not false

17:22 chouser: crios: 'rest' always returns a seq, perhaps an empty one

17:22 you probably want 'next'

17:22 hiredman: :else is not nil and not false, so it can be used as a catch-all there

17:23 technomancy: so... it looks like the use-fixtures function is not really intended for interactive development since it keeps wrapping more and more fixture functions around the test functions rather than being idempotent

17:23 I wonder if there's a way to fix that

17:23 chouser: ,(some #{'b} '(a b c))

17:23 clojurebot: b

17:23 crios: chouser: mmm ok, I check that

17:23 chouser: crios: is that what you want?

17:24 crios: yes :-(

17:24 technomancy: you could store the fixtures as a set, but then you lose the ability to order it.

17:25 crios: chouser: but also studying this: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html , just for "set the stage"

17:25 [memq example is there, written in Scheme]

17:36 lisppaste8: crios annotated #88306 "goes in StackOverflow" at http://paste.lisp.org/display/88306#1

17:37 crios: another try: I'm using next in this implementation, but I get a StackOverflow

17:38 lisppaste8: Chouser annotated #88306 "some other versions" at http://paste.lisp.org/display/88306#2

17:40 crios: thank Chouser; I'll study it. But why :else is not documentated here http://clojure.org/API#toc161 ?

17:41 chouser: crios: it's just convention -- any true value will do

17:41 crios: ah ok, it is a keyword which evalutes to true, isn't it?

17:41 chouser: crios: right

17:43 crios: an other question: in your second example, (recur calls memq itself, right?

17:43 chouser: crios: yes

17:43 but without cosuming a stack frame, so no stack overflow

17:46 crios: it seems that the trick is the (when function:

17:47 chouser: (when x y z) is just (if x (do y z))

17:47 lisppaste8: crios annotated #88306 "untitled" at http://paste.lisp.org/display/88306#3

17:48 crios: I mean, that last implemention doesn't go in StackOverflow

17:48 (thought your is sure better)

17:49 *though

17:52 chouser: (next x) returns nil when x has zero or 1 items left. nil acts as false so we stop looping

17:52 gotta go.

17:57 crios: so here http://paste.lisp.org/display/88306#1 memq is infinitely called with arguments (item nil) ?

17:58 Using when, the recursive call with (item nil) is not tried

17:58 I think it makes sense

18:08 MetaReilly: Are there current instructions for setting up slime and swank manually (NOT using clojure-install)?

18:09 spaceman_stu: is there a way to iterate over a transient vector? something like (doseq [i (transient [1 2])] i)?

18:09 technomancy: spaceman_stu: I don't know if you're supposed to use transients while they're still transient

18:10 mgarriss: let's say i wanted to use clojure to draw a fractal. is the AWT my best bet here for the actual displaying?

18:10 technomancy: mgarriss: clj-processing is probably the easiest

18:10 spaceman_stu: technomancy: get and nth work. Those are along the same lines, no?

18:11 hiredman: spaceman_stu: you would need to use some kind o reduce operation

18:11 of

18:11 spaceman_stu: I don't understand why

18:12 mgarriss: MetaReilly: here is the clojure section of my .emacs, i just started using clojure so it probably has issues but it might help you: http://pastie.org/644604

18:13 MetaReilly: mgarriss: thanks

18:13 hiredman: spaceman_stu: because you are supposed to keep the result of the transient mutation operations

18:13 MetaReilly: mgarriss: i was using the old slime/swank setup from before the new automated install and find the automated setup annoying

18:13 mgarriss: MetaReilly: you'll have to build the swank-clojure jar using maven first

18:14 MetaReilly: me too

18:14 MetaReilly: mgarriss: Thanks

18:14 technomancy: MetaReilly: you could read the source to clojure-install. =)

18:15 MetaReilly: technomancy: I had started to do that and decided that it would be worth asking if somebody had a recipe handy

18:15 hiredman: clojurebot: transient is <reply> Don't bash in place

18:15 clojurebot: 'Sea, mhuise.

18:20 mgarriss: technomancy: clj-processing looks perfect, thx for the lead

18:20 clojurebot: technomancy is to blame for all failures

18:21 hiredman: ~laugh

18:21 clojurebot: ha ha

18:21 technomancy: clojurebot: maybe so, but hiredman is to blame for all errors

18:21 clojurebot: 'Sea, mhuise.

18:21 technomancy: wait, did that just do what I think it did?

18:21 clojurebot: hiredman?

18:21 clojurebot: hiredman is lazy

18:22 technomancy: clojurebot: maybe so, but hiredman?

18:22 clojurebot: maybe so, but hiredman is to blame for all errors

18:22 technomancy: clojurebot: forget maybe so, but hiredman

18:22 clojurebot: I forgot maybe so, but hiredman

20:43 herdrick_: l

20:49 enderoute: how do you set a breakpoint in jswat for a running clojure repl? I see all my functions in the "classes" list to the left, i right click and add a breakpoint, but it doesn't seem to stop when i call the function from the repl

23:32 jaiganesh: hi

23:32 i have a problem

23:33 i am trying to use lcm function but getting this error

23:33 java.lang.Exception: Unable to resolve symbol: lcm

23:33 i have use clojure.contrib.math dont hsi

23:34 i have included the namespace "use clojure.contrib.math"

23:36 anyone?

23:37 hi room

23:37 i have aproblem

23:37 i am trying to use lcm function but getting this error

23:37 java.lang.Exception: Unable to resolve symbol: lcm

23:37 i have included the namespace "use clojure.contrib.math"

23:43 hi room

23:48 adityo: hey

23:54 rongenre: Looking for an idiom: I have a bunch of vectors, all equal length. Want to treat them like a table, search, select based upon it. Like in R with dataframes

23:57 arbscht: ,(doc filter)

23:57 clojurebot: "([pred coll]); "

23:58 rongenre: well sure. I can filter one vector

23:58 arbscht: ,(filter (comp odd? first) [[1 2 3] [4 5 6] [7 8 9] [10 11 12] [13 14 15]])

23:58 clojurebot: ([1 2 3] [7 8 9] [13 14 15])

23:58 rongenre: But I want to use it to index the rest.

23:59 somnium: rogenre: something like (filter identity (map #(filter pred vec) bunch-of-vecs)) ?

23:59 rongenre: so it'd take that to [1 3] [4 6] [7 9] [...]

Logging service provided by n01se.net