# #clojure log - Sep 14 2010

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

0:52 bhenry: what is the reason that + can take 0 args but - cannot?

0:53 wwmorgan: bhenry: - can take a difference, or an opposite. Neither a difference nor an opposite is well-defined for 0 arguments

0:54 bhenry: sum of 0 args is 0, so opposite of 0 args can't be zero?

0:55 ,(- 0)

0:55 clojurebot: 0

0:56 tomoj: is it because they're not commutative?

0:56 they being - and /

0:56 KirinDave: tomoj: I've heard that justification.

0:58 wwmorgan: it's not clear what you're trying to do when you do (-). With (+) or (*), the equivalent is "add/multiply the masses of all the purple giraffes"

0:59 tomoj: whereas with (-) you'd need a particular purple giraffe to go first?

1:01 wwmorgan: Yeah I don't see why (-) would be 0 and not 7 or pi or something

1:02 tomoj: (+ 1) (+ 1 2) vs (- 1) (- 1 2)

1:08 cemerick: KirinDave: did you notice the clojure-colfusion crowd building? That's sure to be the *fourth* audience ;-) http://search.twitter.com/search?q=clojure+coldfusion

1:08 KirinDave: wait wut?

1:08 cemerick: shit you not

1:09 KirinDave: "whats this i dont even"

1:10 tomoj: "Obviously, there is no answer; that is, x = {}." uhhwhat?

1:11 cemerick: bhenry: what's funny about that is that the guy asking the question is probably *the* Alistair Cockburn.

1:12 wwmorgan: he's mixing notation. He should say that for 5 + x = 3 + 2, x = {0} is the answer

1:12 bhenry: tomoj if there is no answer the answer is not zero, there is an empty set of answers

1:12 wwmorgan: similarly, if x * x = 4, then x = {-2, 2}

1:13 jcromartie: i am a coldfusion developer and what is this

1:13 cemerick: jcromartie: I'm starting to think there's a small army of you CFML folks out there.

1:14 jcromartie: I'm kidding. Dear god no.

1:14 I did my time with CFML.

1:14 cemerick: ah, oh well

1:14 jcromartie: but now I stay as far away as possible

1:14 bhenry: http://github.com/seancorfield/cfmljure has 5 watchers. not quite an army

1:15 tomoj: my time was a couple weeks, which was far too long

1:15 cemerick: bhenry: I suspect that a vanishingly small minority of CF guys are even aware of git, nevermind watching a CF/clojure project. :-)

1:16 bhenry: haha touche

1:17 does myspace still use cf? they must have a team of at least three.

1:19 cemerick: We'll have to have a poetry slam at the conj.

1:45 brianstamand: when I launch the lein repl i get an error: which: no rlwrap in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root)

1:45 Anyone know what I'm doing wrong?

1:46 tomoj: maybe try installing rlwrap?

1:47 strange thing is I have no rlwrap on my path and `lein repl` works fine

1:47 brianstamand: I installed lein successfully on one machine (OSX) and didn't get that error. But now on this other (Fedora) machine I'm getting it. I did the same procedure

1:48 well anyway it works now that I installed rlwrap lol

1:48 thanks

1:49 wwmorgan: leiningen falls over to jline if rlwrap isn't installed

1:49 it appears your leiningen thought rlwrap was installed when it wasn't

1:59 tomoj: looks like the error is coming from which

1:59 cgrand: morning clojure people!

1:59 tomoj: maybe which on fedora behaves differently?

2:04 brianstamand: morning cgrand

2:04 tomoj, I have no idea, but I do know that yum install rlwrap seemed to make the error message go away :P

2:06 tomoj: brianstamand: what does `which frobniz` do for you?

2:06 wwmorgan: brianstamand: was there another error message when 'lein repl' failed, after the which line?

2:09 brianstamand: tomoj: /usr/bin/which: no frobniz in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root)tomoj: /usr/bin/which: no frobniz in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root)

2:10 wwmorgan: no, just "REPL started; server listening on localhost:55668." which i dont think is an error msg :)

2:11 wwmorgan: brianstamand: oh. Did you try to connect to the repl server? I suspect everything would have worked?

2:11 brianstamand: the repl didn't actually fail it just spit out the first error message, and then wouldnt run any command right

2:12 how do you connect to the repl server? I'm brand new to this sorry :)

2:12 wwmorgan: oh sorry, I just mean that the repl started up

2:12 brianstamand: yeah the repl seemed to work

2:12 what I've been trying to do is get compojure running actually, and to make compojure work I installed lein

2:13 wwmorgan: aha. I'm pretty sure I know what's going on. I'll submit a fix to leiningen

2:14 brianstamand: cool

2:14 wwmorgan: as far as getting compojure running, that's a mostly painless process

2:23 brianstamand: ya compojure seems to be running properly, from the repl, but i haven't been able to see the Hello World thing for some reason

2:24 ok it's working now. Thanks for the help :) I always learn something when I come to this channel :)

2:42 sandGorgon: hi guys.. i was learning/messing around with core.clj.. I was wondering if there was any way I can load up core.clj (or any other clj files), without having to recompile the jar file ? Going one step further, is it possible to do this without quitting the repl ?

2:45 notsonerdysunny: is it possible to find out if a "promise" has been "deliver"ed without blocking? a simple "deref" would block it...

2:45 seangrove: Hey all, I'm trying to play around with creating a dsl http://pastie.org/1157591

2:45 You can see it's not quite right

2:46 Should I start using macros here... should I be rethinking the sub-exps stuff...

2:48 G0SUB: grinnbearit

2:50 grinnbearit: hey

2:51 wwmorgan: seangrove: you don't need macros, I don't think. I would just make your html function call (apply str sub-exps) and that should do what you want

2:54 notsonerdysunny: looking at the implementation of promise in core.clj makes it look like there is no way, yet, to tell whether a promise has been delivered without blocking

2:54 clojurebot: hiredmans euler.clj is so embarassing

2:56 seangrove: wwmorgan: I'll give that a try :0

2:56 notsonerdysunny: wwmorgan: .. hmm.. that would be very nice to have ..

3:04 wwmorgan: notsonerdysunny: I agree. futures, for example, have something analogous in future-done?

3:07 notsonerdysunny: wwmorgan: yea true

3:20 wwmorgan: I think this behaviour is purposefull.. since it will break the functional-programming paradigm..

3:21 code becomes time dependend...

3:21 *dependent

3:21 sorry .. I am myself not convinced with what I just said..

3:21 wwmorgan: notsonerdysunny: I don't see a problem with it

3:23 notsonerdysunny: wwmorgan: what I noticed is that if a promise has been made in a let block and we don't ever deref it .. it still blocks...

3:26 wwmorgan: notsonerdysunny: can you show me a code example?

3:35 notsonerdysunny: (let [s (promise)] s)

3:35 wwmorgan: *

3:36 ,(let [s (promise)] s)

3:36 clojurebot: notsonerdysunny: Excuse me?

3:36 notsonerdysunny: ->(let [s (promise)] s)

3:36 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: (#'clojure.core/promise)

3:40 wwmorgan: notsonerdysunny: you'll notice that (promise) also blocks

3:41 but not (if (promise) 0 1)

3:41 the reason for this, I believe, is that it's trying to print the promise on the repl, and there's an override for printing an IDeref that dereferences it, which blocks

3:44 notsonerdysunny: wwmorgan: you may be interested in the replies I got from the google clojure group

3:47 seangrove: I can't seem to get this clojure right.. http://pastie.org/1157645

3:47 for some reason it doesn't seem to be extrcting "something" from the array

3:49 amalloy: you need sub-exps#, don't you? it always shouts at me if i try to do that

3:49 seangrove: Ah, that may be it

3:49 I'm not sure where that's documented though

3:49 wwmorgan: seangrove: there are at least two other things wrong

3:50 amalloy: it's documented in the docs for syntax-quote, somewhere

3:50 ,(doc `)

3:50 clojurebot: Unmatched delimiter: )

3:50 amalloy: aww

3:50 ,(doc syntax-quote)

3:50 clojurebot: I don't understand.

3:50 wwmorgan: the macro definition appears to expect a single symbol for an argument, but you're passing it a vector with a symbol in it

3:51 seangrove: wwmorgan: You're right :(

3:52 Thank you... that looks a bit better

3:52 wwmorgan: and, actually, I think it might just work with that change and amalloy's

3:52 amalloy: it gets close

3:53 seangrove: Why do I need sub-exps# ?

3:53 For understanding's sake, of course :)

3:53 amalloy: macros aren't allowed to declare variables "for" the code they expand into

3:54 sub-exps# expands into a gensym which is guaranteed to be a unique variable name

3:54 seangrove: Ah, I see

3:54 Interesting

3:54 Why aren't they allowed to do that?

3:54 amalloy: otherwise you could accidentally shadow a variable

3:55 see http://www.gigamonkeys.com/book/macros-defining-your-own.html where it talks about leaky abstractions

3:55 the general problem is what if your macro used the variable x, and it was called from code that also used x, but for a different thing

3:56 because macros are expanded inline rather than called on the stack, they don't have their own scope so that's a bigger problem than it is for functions

3:56 seangrove: I thought it might be something like that, but it doesn't seem like such a big deal

3:57 Probably worse for those who've been bitten by it :)

3:57 LauJensen: In Clojure its not a big deal

3:57 In CL it is

3:57 In Clojure x resolves to a fully qualified namespace symbol, and #'x to a fully qualified var, so you won't typically get caught in accidental leakeage

3:58 ,`x

3:58 clojurebot: sandbox/x

3:58 LauJensen: ,`#'x

3:58 clojurebot: (var sandbox/x)

3:58 wwmorgan: seangrove: I took a shot at it here http://pastie.org/1157661

3:58 amalloy: yes. it's less of a problem here, but if we didn't have to use gensym# to deal with it, it would surprise us even more in the rare cases when it would otherwise matter

3:58 wwmorgan: notice that ~name became '~name

3:59 seangrove: Oh, interesting

3:59 I have this: http://pastie.org/1157664

3:59 I think that may be my problem :)

3:59 amalloy: yep

4:00 i usually still have to poke around at ~' and '~ and all this nonsense for a while before i remember how they work

4:00 seangrove: And does , do anything like it does in scheme?

4:01 amalloy: no

4:01 it's whitespace

4:01 ,[1, 2,,,,,,,,,,,,,,,,,,,,,,,,,3]

4:01 clojurebot: [1 2 3]

4:02 seangrove: ok

4:02 So in macros, the special characters are `'~#

4:02 4?

4:03 amalloy: well that's...a simplification, but those are the characters that might behave differently than you think in macros

4:03 clojurebot: Barking spiders!

4:03 wwmorgan: ' is just quote, inside or outside of a macro

4:03 also ~@

4:04 amalloy: and ` is "just" syntax-quote inside or outside a macro, but it's unusual to want to use it outside one

4:04 LauJensen: seangrove: ` means that macro reader rules apply in the following form, ~ means eval, ~@ means eval and splice, ie (1 2 3) => 1 2 3, # means gensym

4:04 amalloy: ,(let [arg 'wooo-symbol] `(println ~arg))

4:04 clojurebot: (clojure.core/println wooo-symbol)

4:05 seangrove: Ah, awesome

4:05 Thanks, I think that's really useful

4:05 amalloy: use your powers for good

4:06 seangrove: Hey now... No promises

4:07 LauJensen: (defmacro with-trouble [& body] `(let [~'x 5] ~@body))

4:07 #'user/with-trouble

4:07 user=> (let [x 100] (with-trouble (+ x 5)))

4:07 10

4:07 Thats how hard it is, to get into trouble :)

4:10 seangrove: Nice!

4:10 amalloy: Laujensen! now i'm going to have nightmares!

4:11 LauJensen: hehe

4:11 Rich makes you work hard to have bugs

4:11 amalloy: to be fair, the debug support, even with swank, makes me work hard to fix them too

4:13 LauJensen: hehe, true - its to teach you the lesson of not introducing bugs

4:14 And actually, stacktraces have just been improved in master with the pst function, so you get more accurate details

4:14 amalloy: speaking of which, who's in charge of slime/swank for clojure? i can reproducibly crash emacs

4:14 seangrove: I can't use a macro with do-seq, can I?

4:15 LauJensen: amalloy: I don't know, I'd love to know though. We should ask technomancy!

4:15 \$mail technomancy Who's maintaining slime/swank for Clojure?

4:15 sexpbot: Message saved.

4:15 LauJensen: seangrove: no, but I think it will work with doseq

4:17 amalloy: heh. yes, doseq will work, but map won't

4:17 seangrove: heh

4:17 Ah, I'm using a list, not a vector

4:17 Got it

4:18 amalloy: also i don't think you're using doseq right

4:18 LauJensen: (doseq [t tags] (make-tag t))

4:18 amalloy: that

4:18 er wait

4:19 there was just a discussion on the google group about why that won't work

4:19 LauJensen: Would be a nicer helper though, do have a doit! macro, which didn't take a binding vector but just the collection, and fed 1 item at a time to whichever function was in the body

4:20 tomoj: and how do you refer to the item?

4:20 with % ?

4:20 LauJensen: tomoj: nothing, just wrap the functions in partial

4:21 (doit! coll my-fn)

4:22 tomoj: (comp dorun map) ?

4:22 seangrove: Ah, yes, the macros are compile-time, not runtime...

4:22 amalloy: but you can pass them as literals, since the list of legal HTML tags is unlikely to change very often

4:22 LauJensen: tomoj: doseq is less demanding on the system

4:24 seangrove: Not sure how I would pass them in as literals - the macros are expanded literally in-place, right?

4:25 tomoj: LauJensen: only because it doesn't have to call your function, right?

4:25 seangrove: I could re-write make-tag so that it took a list of tags to make and used doseq there

4:25 amalloy: right

4:26 tomoj: I mean, if the 'body' for doit! is passed as a function, you can't macroexpand the body out like you can with doseq, right?

4:26 LauJensen: tomoj: map allocations a new sequence which doseq doesn't IIRC

4:26 s/allocations/allocates/

4:26 sexpbot: <LauJensen> tomoj: map allocates a new sequence which doseq doesn't IIRC

4:26 tomoj: right, doseq expands to a loop/recur over the seq, chunking

4:26 amalloy: better would be to leave make-tag alone (or turn it into a function instead of macro) and add make-tags that takes a seq

4:27 LauJensen: only use functions if you must control evaluation of the arguments

4:27 then and only then, will I allow it

4:27 amalloy: er, only use macros?

4:27 LauJensen: yea

4:27 :)

4:28 seangrove: amalloy: The reason I thought it should be a macro instead of a function is that I need it to define functions for me - will a defn inside of a function affect the current ns?

4:28 * seangrove tries to see...

4:28 tomoj: aha

4:29 do you only have the names for the vars at runtime?

4:29 if so, how would you pass them to defn without a macro?

4:30 seangrove: No, they're available ahead of time

4:30 tomoj: ok

4:30 seangrove: Doesn't look like I can do it with defn... at least not in a way that jumps out at me immediately

4:31 amalloy: you can do something like this:

4:31 (defn gimme-code [a] `(println ~a))

4:31 (defmacro write-stuff [& stuff]

4:31 `(do

4:31 ~@(map gimme-code stuff)))

4:31 tomoj: I was thinking you wouldn't get line numbers and file information on defns done inside a function, but you do

4:32 amalloy: ie, you use your defn to create the code block, and just use the macro to control evaluation of args and expand the defn's code in place

4:32 seangrove: amalloy: So the defn is only for the body of the function?

4:33 amalloy: user=> (macroexpand '(write-stuff 10 11))

4:33 (do (clojure.core/println 10) (clojure.core/println 11))

4:33 tomoj: that is kinda neat

4:33 then you can just call the functions to test parts of your macro

4:34 amalloy: it's hard for me to really grasp, but macros are just functions that control evaluation and expand in place; so you can use functions instead of macros to do repetitive work for them

4:34 tomoj: yeah, I think macro-utility functions are a lisper thing?

4:34 support code for code generation

4:34 amalloy: tomoj: not sure what you mean by a lisper thing?

4:35 tomoj: I mean, if you are a wise lisper and have attained homoiconicity enlightenment, you have probably used this technique

4:36 amalloy: ah. well i haven't really reached enlightenment yet, but i'm good at noticing the fiddly bits

4:36 tomoj: but I wouldn't know, rich hickey is a western guru and I have hardly begun on the path to lisp nirvana

4:37 amalloy: ooc i don't suppose we have any bridge players in here?

4:37 tomoj: 'ooc'?

4:38 amalloy: out of curiosity. i can never tell which abbrevs will be recognized where

4:38 tomoj: ah

4:38 amalloy: i figured with ymmv practically an icon of irc, i could get away with ooc here :P

4:38 tomoj: I could think of only "out of character", I was going to ask, are you not actually a clojure programmer but only roleplay as one in #clojure? :D

4:38 amalloy: some days it seems that way...:)

4:39 but then i discover ingenious ways to use the language built-ins and all is well

4:39 jjido: how do I change a list-building recursive call into a (recur)?

4:40 I have this in merge-sorted-lists-rec: (cons x1 (merge-sorted-lists-rec (rest a1) a2))

4:40 seangrove: Doesn't seem quite right :P http://pastie.org/1157700

4:41 amalloy: jjido: add a parameter to hold the current result list, and cons onto it before recurring

4:41 seangrove: (macroexpand '(stuff)), not (macroexpand (stuff))

4:42 tomoj: seangrove: happen to use emacs? I won't beat you up if you don't, it's just there's a neat trick you should know if you happen to

4:43 seangrove: Yup, emacs

4:43 amalloy: and also you have to pass the list literally, in place, without a def: (macroexpand '(make-tags [a abbr address]))

4:43 seangrove: amalloy: Just came across that epiphany now :)

4:43 * amalloy perks up for an emacs tip

4:44 tomoj: seangrove: if you have it set up for clojure, put point on the first paren in a macro call, and hit C-c C-m

4:44 seangrove: I'm in clojure mode, but I get "C-c RET is undefined"

4:46 talios: Evening

4:46 amalloy: tomoj: neat! that is super-handy

4:46 tomoj: seangrove: you need slime set up

4:46 it can't macroexpand without talking to clojure

4:46 amalloy: tomoj: i'm a bit sad that point has to be *exactly* on (before, if you use | caret instead of block) the first paren, though

4:47 LauJensen: tomoj: I didn't know about that one, thanks

4:47 tomoj: yes

4:47 talios: gah - "You don't have org.clojure permissions, so the staging artifacts went into default 'Central Bundles' profile, artifacts in which need to be reviewed and released by us." - tripped by trying to deploy clojure to maven central :(

4:48 amalloy: ugh, i'm going to have to fix this C-c C-m trick to use pprint - it's not very useful when it's printed raw

4:49 seangrove: amalloy: Doesn't quite expand correctly I think, still just putting it in literally: http://pastie.org/1157705

4:49 tomoj: amalloy: hmm

4:49 seangrove: tomoj: Thanks, I'll check it out when I turn slime back on :)

4:49 tomoj: amalloy: my output looks like this https://gist.github.com/00c6fe4818b1722a27c6

4:49 if yours is uglier, try upgrading to swank-clojure 1.3.0-SNAPSHOT

4:50 (that's (for [x [1 2 3]] (* x x)), btw)

4:50 amalloy: seangrove: that's weird. your code looks about right to me. i'll poke around at it

4:51 tomoj: the case of doit! brings up an interesting question for me

4:52 would it be a good thing to be able to easily create macros which expand to loop/recur iteration over chunked sequences?

4:52 or is having the set of primitives which deal with chunked seqs nicely and building things out of them enough?

4:52 seangrove: I just had an epiphany - if you can serialize continuations, then you could pause execution, serialize the current continuation, send it over the network to another machine, and continue execution there

4:53 Is that right?

4:53 And have I been missing that aspect all along with image-based development?

4:54 amalloy: seangrove: don't pass your list of tags as a vector, pass it raw. OR, take the & out of make-tags

4:54 tomoj: apparently some scala work has been done with serializable continuations http://www.scala-lang.org/node/3485

4:55 my understanding had been that you might pass around references to continuations (like session ids) but that they'd have to come back to the same process to be continued

4:55 seangrove: amalloy: Yup, that was it, I think

4:55 tomoj: but smalltalk can serialize them according to some hn comment

4:55 amalloy: seangrove: i know! i had to try it out myself before i was confident enough to claim to have the answer :)

4:56 tomoj: unfortunately we don't have decent continuations in clojure

4:56 LauJensen: tomoj: you can read why on the google group. In its first year I remember Rich arguing for why he didn't want continuations, at least at that time

4:56 (clojure's first year)

4:57 tomoj: "He reported having good results by not keeping session state in web servers but using serializable continuations to keep the state exclusively on the clients"

4:57 buh-what?

4:57 if someone cracks your serialization scheme, don't they get to execute arbitrary code?? :O

4:58 amalloy: tomoj: no clojure programmers would ever do anything evil. don't be silly

4:58 gregh: all the server has to do is sign the data held by the client

4:58 (and verify the signature)

4:59 tomoj: ok

4:59 I thought there might be some cryptographic solution

4:59 gregh: yeah, signing. :)

4:59 it can be as simple as hash(data+secret)

5:02 brianstamand: (hash data secret) ? :P

5:02 (hash (+ data secret)) ? :P

5:02 tomoj: hmac better I guess

5:04 gregh: touche, brianstamand :)

5:08 amalloy: okay, night folks

5:08 LauJensen: nighty night

5:08 seangrove: Thanks again amalloy

5:09 amalloy: np seangrove. see you around

5:09 it's a blast to be the one on the helping side for a change

5:24 jjido: is it faster to build the list by appending stuff at the end (concat b [x1]) or to insert the element in front then reverse when done?

5:25 LauJensen: jjido: Use a vector + conj, thats the fastest

5:25 tomoj: the latter, but are you sure you want a list?

5:25 yeah

5:26 LauJensen: ,(time (dotimes [_ 1e6] (conj [1 2 3] 4)))

5:26 clojurebot: "Elapsed time: 361.497 msecs"

5:26 LauJensen: ,(time (dotimes [_ 1e6] (reverse (cons 4 '(1 2 3)))))

5:27 clojurebot: "Elapsed time: 2023.508 msecs"

5:41 tomoj: a bit unfair I think

5:41 ,(time (do (reduce conj [] (range 2e6)) nil))

5:41 clojurebot: "Elapsed time: 3708.875 msecs"

5:41 tomoj: ,(time (do (reverse (reduce conj () (range 2e6))) nil))

5:41 clojurebot: java.lang.OutOfMemoryError: Java heap space

5:41 tomoj: darn

5:41 ,(time (do (reverse (reduce conj () (range 1e6))) nil))

5:41 clojurebot: "Elapsed time: 4790.578 msecs"

5:42 tomoj: ,(time (do (reduce conj [] (range 1e6)) nil))

5:42 clojurebot: "Elapsed time: 1622.785 msecs"

5:42 LauJensen: I don't think its unfair. Most decisions between lists and vectors are based on where you want to append.

5:42 Doing it one way then reversion is just a sign that you've picked the wrong data structure

5:42 tomoj: I mean it's really more like 3x slower, not 5.6x slower

5:42 still much slower :)

5:43 jjido: how do I make a vector from take, drop, rest and concat operations?

5:43 tomoj: in linear time

5:43 raek: ,(vec (list 1 2 3)) ; linear time

5:43 clojurebot: [1 2 3]

5:43 LauJensen: jjido: look at subvec and rseq, and see if you can model around them

5:43 mrBliss: or (into [] (take ..

5:44 LauJensen: They are O(1) IIRC

5:44 ,(doc subvec)

5:44 clojurebot: "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."

5:44 tomoj: you can peek and pop vectors

5:44 LauJensen: ,(doc rseq)

5:44 clojurebot: "([rev]); Returns, in constant time, a seq of the items in rev (which can be a vector or sorted-map), in reverse order. If rev is empty returns nil"

5:44 LauJensen: ,(doc peek)

5:44 clojurebot: "([coll]); For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil."

5:44 LauJensen: ,(doc pop)

5:44 clojurebot: "([coll]); For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as next/butlast."

5:46 jjido: I am just coding a merge sort, learning experience

5:48 tomoj: that is my current code http://pastebin.ca/1940405

5:53 raek: I'd suggest to use either vector operations or sequence functions, but not both

5:53 currently, it contains no vector-specific code and yields a sorted sequential view of any collection

5:54 a vector-only version might be more performant, but less general

5:54 LauJensen: raek: sequence functions for a tight loop in a fn like that?

6:02 jjido: is this better? http://pastebin.ca/1940413

6:03 raek: also, the indentation is a bit misleading

6:05 jjido: sorry. I wrote it as if ... else if ... originally, then rewrote in Clojure. I can fix that

6:06 raek: I pasted it into emacs, selected it, pressed tab and put it back into pastebin: http://pastebin.ca/1940416

6:06 jjido: the new version seems faster

6:06 LauJensen: jjido: should be a lot faster, try doing a million repeats (1e6) and timing both the old and the new

6:08 raek: would it be faster if one did the vec call only on the final result, and not in every merge step?

6:08 jjido: raek: the vec call is only when one list is empty

6:09 (vec (concat b a2)) -> both b and a2 are vectors

6:10 and a2 should (usually) be small

6:10 raek: oh, right.

6:12 also, nested ifs like (if p1 e1 (if p2 e2 e3)) can be written with cond: (cond p1 e1 p2 e2 :else e3)

6:14 mrBliss: I translated the pseudo code mergesort from wikipedia into my own clojure version: http://gist.github.com/578831

6:21 jjido: mrBliss: mine's slightly faster on my computer, but yours is shorter :)

6:22 mrBliss: I've added a version of my mergesort optimized for vectors, it's a bit faster http://gist.github.com/578831#file_gistfile1.clj

6:23 mine is two times shorter than the pseudocode version on wikipedia :)

6:25 jjido: it is a winner

6:28 mrBliss: still 6 times slower than clojure.core/sort, but that's actually Arrays.sort

6:28 jjido: what is the difference between (/) and (quot)?

6:28 LauJensen: ,(/ 5 2)

6:28 clojurebot: 5/2

6:28 LauJensen: ,(quot 5 2)

6:28 clojurebot: 2

6:29 jjido: ok using quot makes my algo a little faster

6:29 bozhidar: quot returns only the fixnum part of the division

6:29 LauJensen: ,(doc case)

6:29 clojurebot: "([e & clauses]); Takes an expression, and a set of clauses. Each clause can take the form of either: test-constant result-expr (test-constant1 ... test-constantN) result-expr The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can follow the clauses, and its va

6:29 LauJensen: case is faster than if/cond IIRC

6:30 mrBliss: case handles 1 expression, but we need 2 (left and right)

6:35 apparently (= 0 (count coll)) is slightly faster than (empty? coll)

6:35 LauJensen: mrBliss: empty? calls seq, where count is just reading a field

6:36 mrBliss: figured that out after slime-edit-definition on empty? :)

6:37 LauJensen: partly

6:37 You'd also want to run an slime-inspector on any collection to see the count field

6:37 mrBliss: jjido: your version is slightly faster on my machine

6:38 jjido: I could use case in merge-sort-rec, but does it have a default clause?

6:40 ok I just need to omit the condition

6:41 LauJensen: ,(case nil true "even" false "odd" "neither")

6:41 clojurebot: "neither"

6:41 jjido: not faster.

6:41 LauJensen: ,(case (even? 2) true "even" false "odd" "neither")

6:41 clojurebot: "even"

6:48 mrBliss: I give up: http://gist.github.com/578831#file_gistfile2.clj Just a bit faster

6:50 LauJensen: looks good

6:58 fbru02: what's the most usual cause of java.lang.Integer cannot be cast to clojure.lang.IFn ? I mean somehow i keep getting that in my spikes ...

6:59 LauJensen: ,(5 {5 6 7 8})

6:59 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

6:59 LauJensen: fbru02: Its always a case of you putting an Integer in the position of a callable, ie. first place in a list

6:59 ,({5 6 7 8} 5)

6:59 clojurebot: 6

7:01 fbru02: LauJensen: thanks

7:02 LauJensen: np

7:19 octe: in clojure projects, is it correct to use the same package as a namespace as you'd use with java?

7:19 like com.example.myproject

7:19 or just myproject directly?

7:21 rhudson: Yes, that's a reasonable naming scheme for namespaces

7:22 LauJensen: octe: Don't just one a single name like 'myproject'

7:25 fbru02: hey guys i think this is too much of an open question but i want to create a macro to build normalized equations of the form ax^n + bx^(n-1)... + cx + d = f(x) , so i can later evaluate them etc like f(2) and will give me the result

7:26 the question is what should i be giving as an input ? a vector of coeficientes ? and as output a partial function?

7:26 LauJensen: fbru02: macros are for controlling evaluation

7:28 rhudson: I'd say the first step is to write a function that takes a vector of coefficients and a value.

7:28 fliebel: What was the channel for cake? More troubles on my side...

7:29 fbru02: rhudson: what is the value for ?

7:29 rhudson: That's the x

7:30 fbru02: rhudson: ah nono, but i want to return a lambda (fn (x))

7:31 rhudson: Well, write the evaluation function first, then there's various techniques (e.g. partial) to give you a function of x

7:32 Given (poly coeffs x), you can for instance (defn fpoly [coeffs] (fn [x] (poly coeffs x))

7:32 LauJensen: fliebel: #cake.clj ?

7:33 fbru02: rhudson: thanks, so basically what's the step for going from defn to defmacro:?

7:33 rhudson: Well, why do you need a macro?

7:33 fliebel: LauJensen: jep :)

7:34 rhudson: fbru02, as a general rule, if you can do something with functions, you shouldn't bother with macros

7:37 fbru02: rhudson: thanks again :) but the thing is , i been trying to do this with functions and the glue them together as in here http://pastie.org/1157934 but then i figured as they look alike maybe i can extract everything in to a macro? right?

7:41 rhudson: Given that fpoly function as above, (defn make-linear [a] (fpoly [a]))

7:41 (defn quadratic [a0 a1] (fpoly [a0 a1])) etc

7:46 fbru02: rhudson: good idea i will try it out

7:47 bartj: I rarely ever use partial, and I find it odd

7:47 can anyone give a practical use case which forces me to use it?

7:47 rhudson: bartj, I don't like it much myself

7:48 LauJensen: bartj: for moustache handlers for instance, you can either do ["/"] #(my handler my-arg %) or ["/"] (partial my-handler my-arg). In such cases i prefer partial

7:48 fliebel: bartj: Some cases where you'd use an anonymous function, a partial fits better. It is also useful for making several similar functions.

7:49 bartj: fliebel, when I think of similar functions, I think of closures :)

7:49 fliebel, am I wrong

7:50 fliebel: bartj: Both are higher order functions. In simple cases, partial might be… simpler.

7:51 bartj: LauJensen, that seems like a nice example, thanks!

7:55 fliebel, now that you mention it, partial seems more "cleaner" (?) than anonymous functions, imo

7:55 fliebel, I never thought of it that way

7:56 fliebel: bartj: I use them all the time in Python, because the lack of proper lambdas.

7:58 bartj: fliebel, I didn't know Python had partial :)

7:59 fliebel, I also feel Python doesn't enforce "functional" thinking in the same way Clojure does - but, that is a topic for another day

7:59 rhudson: The relative advantage of anon funcs is that it's manifest how many args need to be supplied

8:00 fliebel: bartj: It's in functools. It doesn't enforce it at all, but Clojure does effect my Python style.

8:00 bartj: also, I am always a bit nonplussed re: anonymous functions vs. functions

8:01 currently, if a function is very tiny (one or two statments) and is not called from multiple other functions, I make it anonymous

8:01 fliebel, yes, just looked it up here - http://docs.python.org/library/functools.html

8:56 * stephyn I need to determine if a value is in a vector and what its index is?

8:57 fliebel: stephyn: set?

8:58 rhudson: ,(doc vector?)

8:58 clojurebot: "([x]); Return true if x implements IPersistentVector"

8:58 * stephyn "Returns true if x implements IPersistentSet"

8:58 rhudson: & (count v) gives you the size

8:58 stephyn: I have a vector of numbers. [1 5 7 10]. I need to determine if it contains 4 and what its index is if it does.

8:59 rhudson: Then you have to search through the vector, one way or another.

9:00 cinim0d: http://richhickey.github.com/clojure-contrib/seq-utils-api.html -- Check for find-first

9:01 * stephyn close, thanks.

9:01 rhudson: sorry, missed that you said "value is IN a vector"

9:01 tomoj: huh, deftypes don't get docstrings?

9:02 * stephyn no worries. what I really want is (index-of coll val)

9:02 * stephyn well, really it needs to work on vectors only (probably) so (index-of vec val)

9:02 tomoj: vectors will be no help

9:03 unless they're sorted vectors

9:04 don333: just curious why do keep using /me form stephyn?

9:06 tomoj: ,(require 'clojure.contrib.seq-utils)

9:06 clojurebot: nil

9:06 tomoj: ,(->> (clojure.contrib.seq-utils/indexed [:a :b :c :d :e]) (clojure.contrib.seq-utils/find-first (comp #{:d} second)) first)

9:06 clojurebot: 3

9:06 tomoj: there must be a prettier way of doing that

9:07 (first (find-first (comp #{:d} second) (indexed [:a :b :c :d :e])))

9:08 cinim0d: You could also write index-of ^^

9:09 tomoj: my question is whether there is a prettier way of writing index-of

9:09 stephyn: I was sort of surprised it didn't exist...I'm just learning and I've already re-written a number of functions :O

9:09 tomoj: you tend to use indexes far less often in clojure than in some other languages

9:10 stephyn: well, perhaps I need a different idiom to attack the problem. Are you familiar with the "Programming Challenges"?

9:10 tomoj: I'm not

9:11 sometimes there is probably no better way than to use indexes, but it's just rarer in clojure, I think

9:11 because you can often get what you want just by mapping, reducing, filtering

9:12 stephyn: well, this particular problem has a stack of blocks...which, to me, indicates an ordered list of the blocks (referenced by number) and you need to find blocks in the stacks and move them around (including the blocks above them)

9:12 chouser: if you get the index, you then generally have to use it to look up something else. possibly you can use map to walk both things at once and not have to use an index at all.

9:13 tomoj: stephyn: are you new to functional programming?

9:15 stephyn: do you happen to have a link to the problem?

9:15 if you're new to FP it can sometimes be difficult to think of a functional-style solution

9:16 fliebel: stephyn: I second that. I tend to start of with an atom for some sort of state I don't need in the end.

9:17 tomoj: stephyn: for future reference, better to stay in the channel: get more feedback if it catches someone's eye

9:23 stephyn: yes, I don't think you need indexes for that problem

9:26 jjido: you will find it easier to create a new list with the desired data instead of updating the existing one in Clojure

9:45 arkh: I'd like to take an sequence of RE's and attempt to match them against a string. If any one of the RE's match, I'd like to return something truthy, else nil. Any recommendations?

9:46 mrBliss: (some #(re-matches % s) [re1 re2...])

9:46 arkh: mrBliss: thank you

9:47 tomoj: stephyn: seems you do probably need some indexes

9:48 stephyn: tomoj: it still seems interesting to try something different. I'm thinking more of the SICP "build a language that solves the problem" approach.

10:00 bhenry: stephyn http://media.pragprog.com/titles/shcloj/flow.pdf search for index-filter and index-of-any. not exactly what you want, but you could build from there.

10:01 stephyn: bhenry: thanks.

10:34 arkh: sorry for all the noob questions, but I'd like to "split" a string similar to Perl or Python, and split-with in clojure is giving me no joy

10:34 ,(split-with #(= '.' %) "172.16.102.0")

10:34 clojurebot: [() (\1 \7 \2 \. \1 \6 \. \1 \0 \2 \. \0)]

10:34 arkh: : (

10:36 ,(split-with #(= \. %) "172.16.102.0")

10:36 clojurebot: [() (\1 \7 \2 \. \1 \6 \. \1 \0 \2 \. \0)]

10:37 fliebel: ,(split-with +(= \. %) "..............172.16.102.0")

10:37 clojurebot: java.lang.Exception: Unable to resolve symbol: =  in this context

10:37 fliebel: ,(split-with +(= \. %) "..............172.16.102.0")

10:37 clojurebot: java.lang.Exception: Unable to resolve symbol: % in this context

10:37 fliebel: doh

10:37 MayDaniel: Use clojure.string/split

10:37 chouser: ,(.split #"\." "172.16.102.0")

10:37 chouser: ,(seq (.split #"\." "172.16.102.0"))

10:37 clojurebot: ("172" "16" "102" "0")

10:38 arkh: thank you! I didn't even know about clojure.string

10:39 chouser: what you used is java String, right?

10:40 chouser: arkh: Java's regex Pattern has a .split method

10:40 that's what I used

10:40 arkh: oh ... cool

10:41 fliebel: I keep forgetting to look at Java docs when looking for a function.

10:41 arkh: I totally should have known that : / #"\." is no String

10:44 and I think that exact line chouser wrote should be a clojure built-in, imho.

10:45 jjido: ,(doc clojure.string/split)

10:45 clojurebot: "([s re] [s re limit]); Splits string on a regular expression. Optional argument limit is the maximum number of splits. Not lazy. Returns vector of the splits."

10:46 arkh: fair enough

10:47 jjido: ,(closure.string/split "172.16.4.12" \.)

10:47 clojurebot: java.lang.ClassNotFoundException: closure.string

10:48 Raynes: jjido: You just typo'd a typo.

10:48 jjido: lol

10:49 ,(clojure.string/split "172.16.4.21" \.)

10:49 clojurebot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.util.regex.Pattern

10:50 jjido: ,(clojure.string/split "172.16.4.21" #"\.")

10:50 clojurebot: ["172" "16" "4" "21"]

10:51 jjido: ok

11:06 rickmode: If there some equivalent to defonce when using a let like the following? (let [count (atom 0)] (defn counter [] (swap! count inc)))

11:11 fliebel: How helpful are the docs of Enlive… (doc template) => A template returns a seq of string.

11:11 jjido: you could use binding to move count in a separate thread maybe?

11:12 fliebel: (doc snippet) => A snippet is a function that returns a seq of nodes.

11:12 clojurebot: Gabh mo leithscéal?

11:13 stuarthalloway: Hello!

11:13 fliebel: stuarthalloway: Hey

11:14 stuarthalloway: Anybody here know the address for the studio backchannel?

11:14 ...for those of us currently in clojure training...

11:14 laurus: How do I log a REPL session to a file?

11:18 There's no way to get a session transcript in Clojure?

11:27 Is (. System exit 0) the proper command to exit the Clojure REPL?

11:27 Raynes: (System/exit 0)

11:27 laurus: Thanks Raynes :)

11:29 jjido: control-d should work too or is that bad?

11:29 laurus: jjido, I just wanted an actual Clojure command to do it :p

11:30 Raynes: jjido: Nothing wrong with exiting a command-line REPL like that.

11:30 ivey: What's wrong with C-c C-k?

11:30 Raynes: laurus: Incidentally, that's actually the Java way of doing it. It's just kind of pointless to wrap it in Clojure.

11:30 * ivey grins

11:31 laurus: Raynes, yeah, I see. Actually I just did this: (defn exit [] (System/exit 0))

11:31 ;)

11:31 Raynes: That's fine. Wrapping it in Clojure itself would be a little pointless.

11:31 laurus: Right

11:33 By the way, in case anyone's interested, I think I found the answer to my question about the REPL transcript: http://www.mail-archive.com/clojure@googlegroups.com/msg18813.html

12:22 kjeldahl: I'm having some trouble with telling clojure to look for libraries/namespaces in another directory. I'm using the traditional clj startup script. Any pointers to how I can instruct the clj repl to look other places for sources (.clj files)?

12:30 seangrove: ,(dotimes [x 5] 'a)

12:30 clojurebot: nil

12:30 seangrove: Is there a way I can collect the the return value from each of the dotimes?

12:31 seangrove: no, dotimes is an imperative loop for side-effecty things

12:31 ,(repeat 5 'a)

12:31 clojurebot: (a a a a a)

12:31 drewr: seangrove: use map or for

12:31 chouser: ,(for [x (range 5)] 'a)

12:31 clojurebot: (a a a a a)

12:31 seangrove: ,(doc repeat)

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

12:32 seangrove: Cool, thanks :)

12:32 kjeldahl: chouser: I'm not having any luck. Clojure shows the following dir in my classpath: /home/marius/src/ai-contest-planetwars-clj/src . In that dir, there is a dir named pw, and a file planetwars.clj . "(use 'pw.planetwars)' gives a filenotfound exception. Can't figure out why.

12:33 Any idea?

12:33 The exact error is: java.io.FileNotFoundException: Could not locate pw/planetwars__init.class or pw/planetwars.clj on classpath: (NO_SOURCE_FILE:0)

12:33 I've confirmed that /home/marius/src/ai-contest-planetwars-clj/src/pw/planetwars.clj is there.

12:33 tomoj: kjeldahl: how are you starting clojure?

12:34 mrBliss: kjeldahl: I've had similar problems, leiningen solved them for me

12:34 kjeldahl: With the clj-env-dir script. But I've confirmed the the classpath inside the repl with " (println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))"

12:34 tomoj: yes, you should really just use lein, there's a project.clj already conveniently there for you

12:35 kjeldahl: I'm not building, I just want it to read a source file...

12:35 tomoj: and lein helps you do that by downloading the libs and starting repls or swank servers

12:35 s/lib/deps

12:36 otherwise, you'll just have to get the deps manually and set the classpath properly yourself

12:36 inspecting (System/getProperty "java.class.path") in your repl would be a good step towards doing that, if you wanted to for some reason

12:38 kjeldahl: Problem is that I'm trying to keep a source tree outside of a common project (that I do not make) without including all the source files from that project.

12:39 Hm, there's obviously something about the source dependencies I'm not getting. I'm not a java guy either, so that probably explains it.

12:39 chouser: It's got to be your classpath(s)

12:40 kjeldahl: It is: (System/getProperty "java.class.path") outputs "/home/marius/.clojure/jline-0.9.94.jar:/home/marius/.clojure/clojure.jar:/home/marius/.clojure:/opt/clojure-contrib/target/clojure-contrib-1.2.0.jar:/home/marius/src/ai-contest-planetwars-clj/src"

12:41 chouser: that's one of them, yes.

12:41 kjeldahl: That last dir, ending with src, contains pw/planetwars.clj .

12:46 chouser: (.getResource (clojure.lang.RT/baseLoader) "pw/planetwars.clj") returns nil?

12:46 tomoj: that doesn't make sense

12:48 chouser: (mapcat #(.getURLs %) (take-while identity (iterate #(.getParent %) (clojure.lang.RT/baseLoader))))

12:48 That's something closer to the actual classpath being used by Clojure, I think.

12:49 mine has 664 entires O_o

12:49 kjeldahl: chouser: Sense or not, that is what it does.

12:49 (returns nil)

12:50 chouser: heh, I didn't say it didn't make sense. That's just par for the course with classpath.

12:50 ok, returning nil makes sense. That simply means the classpath being used by clojure doesn't contain your .clj file

12:50 which we essentially already knew.

12:50 * kjeldahl smiles

12:51 kjeldahl: It also means clojure doesn't use java's classpath or?

12:51 chouser: the question then is does the classpath being used by Clojure have the entries that we think it does.

12:51 kjeldahl: java has many classpaths

12:51 yay

12:52 (filter #(re-find #"/home/" %) (map #(.getPath %) (mapcat #(.getURLs %) (take-while identity (iterate #(.getParent %) (clojure.lang.RT/baseLoader))))))

12:52 try that.

12:52 kjeldahl: The correct path is also in the first mapcat thingy suggested.

12:53 filter thingy: ("/home/marius/.clojure/jline-0.9.94.jar" "/home/marius/.clojure/" "/home/marius/src/ai-contest-planetwars-clj/src")

12:53 chouser: ok, now *that* doesn't make sense. :-)

12:53 kjeldahl: chouse: Yeah, I guess my experimentation leaves a trace.. ;-)

12:55 chouser: hm, all my directory classpath entries end in /

12:55 could it be that?

12:57 kjeldahl: Even if I add the trailing slash where I set the classpath, it's still removed when I display it in clojure.

12:59 chouser: kjeldahl: huh.

13:01 kjeldahl: chouser: Yes, I promise. I changed it to "..srccc/" just to verify that it actually changes within the repl. It does, but it strips the /.

13:03 Forget it. As suspected, operator error.

13:04 Missed a hyphen in the long path.

13:09 seangrove: How should I check if a variable is ... one of these {:a 5 :b 10}

13:10 Is that really a PersistentArrayMap?

13:10 grignaak: ,(map? {:a 10 :b 10})

13:10 clojurebot: true

13:11 grignaak: seangrove: ^^

13:11 seangrove: Ah, good stuff :)

13:11 Thanks

13:15 boojum: seangrove: but it will mutate into a PersistentHashMap when it grows

13:16 afair

13:24 jweiss: is there any way to interact with java libs that require annotations (for instance, testng)? i saw some posts saying that proxy doesn't support annotations but that was a year ago. still true?

13:29 abrenk: jweiss: Clojure 1.2 has annotation support, see "2.12 Java Annotations" in http://github.com/clojure/clojure/blob/1.2.x/changes.txt

13:31 seangrove: I can't see to destructure this correctly

13:31 How can I iterate over {:a 50 :b 100 :c 34} assigning each k:v to key value and doing something with them?

13:32 tomoj: ,(for [[k v] {:a 50 :b 100 :c 34}] (str k v))

13:32 clojurebot: (":a50" ":b100" ":c34")

13:32 lancepantz: seangrove: you want to use for

13:32 tomoj: like that?

13:32 lancepantz: there ya go

13:32 seangrove: Haha

13:33 Yes, that's it

13:33 dakrone: ,(map (fn [[k v]] (println "key:" k "val:" v)) {:a 1 :b 2 :c 3}

13:33 seangrove: I had some hacky thing involving (take 2)...

13:33 dakrone: ,(map (fn [[k v]] (println "key:" k "val:" v)) {:a 1 :b 2 :c 3})

13:33 clojurebot: (nil nil nil)

13:33 tomoj: if by "do something with them" you mean do side effects, that's a different story

13:33 dakrone: alright, well that works, but doesn't show up

13:33 seangrove: No, no side effects

13:33 lancepantz: seangrove: note you'll have to wrap that in (into {})

13:33 tomoj: well, just replace 'for' with 'doseq'

13:33 good :)

13:33 lancepantz: that's if you want a map back out

13:34 seangrove: Nope

13:34 Converting it all to strings in the end

13:34 Trying to add in attributes for my html tags :)

13:46 kotarak: Oeh? Does definterface require AOT compilation?

13:52 dnolen: kotarak: I didn't think so.

13:52 pretty sure it's dynamic

13:53 kotarak: dnolen: ah. Ok.

14:24 jfields: is there an easy way to shutdown a java process if an exception occurs on any thread? I have an app that has a few (future) calls, and I want the whole thing to shutdown if an exception occurs in the main app or the futures.

14:24 (an unhandled exception that is)

14:25 morphling: is there no function like assoc instead of assoc-in for update-in?

14:25 update-in uses (assoc m k (apply f (get m k) args)) internally

14:27 ohpauleez: jfields: Like (System/exit)?

14:28 joshua-choi: I've got a question. I want a sequential data structure that can split any of its elements into two, for text piece tables.

14:29 Essentially replacing that element with something else and splicing another thing after too.

14:29 Are finger trees what I want?

14:29 chouser: joshua-choi: probably

14:29 joshua-choi: How are you finger trees going? :)

14:30 chouser: pretty well. If they pick my finger-tree talk to be at clojure-conj, I'll have to get them wrapped up in the next few weeks.

14:30 jfields: ohpauleez, I get that I can call system exit anytime. was hoping for something that wouldn't require me to put a try catch in my future that calls system.exit

14:30 joshua-choi: If there are any other Clojure data structures that might work, I'd love to know too...I want to make a text editor.

14:30 chouser: jfields: hm, some kind of global default error handler.

14:30 ohpauleez: yeah, that's what I would say too

14:31 use an error handler, or use error-kit on the entire system

14:31 chouser: actually, I'd look at the thread pool classes to see if that's parameterized there.

14:31 clojurebot: error-kit is http://pragprog.com/magazines/2009-07/when-things-go-wrong

14:32 jfields: yeah, Thread/setDefaultUncaughtExceptionHandler looks like what I need

14:33 ohpauleez: chouser: What's the likelihood of finger trees making their way into core? or a contrib for new data structures

14:35 chouser: ohpauleez: almost certainly they'll get into contrib. core has a chance, of course that's up to rhickey.

14:35 ohpauleez: cool, I just started looking into them, they seem quite useful

14:36 chouser: ohpauleez: yeah, very versatile

14:37 I wish I could get performance closer to sorted-maps, vectors, etc.

14:37 But I'm concentrating on API now.

14:38 joshua-choi: chouser: Would you say that the API is stable?

14:38 chouser: no

14:38 sorry

14:48 joshua-choi: chouser: No, it's fine. I'm just really happy that they're being implemented at all. Thanks for doing it!

14:51 chouser: sure! I hope they end up being useful.

15:11 joshua-choi: chouser: In your finger trees' finger-tree function, what is meter-obj? (finger-trees meter-obj x y z).

15:12 chouser: joshua-choi: something that implements ObjMeter

15:13 Such as len-meter

15:13 jweiss: if i want to write some clojure functions and turn them into a java class, and have the java testng library pick up my class and run it based on annotations on the public methods in the class, how would i do that? i'm not implementing any interface nor extending a class.

15:13 dmiller2718: rhickey: Will you be processing pending CAs anytime soon? Kurt S. sent one in on 8/16. He has redone the build process for ClojureCLR and I'm itching to get those changes in.

15:13 jweiss: i basically want an empty protocol, with annotated fn's -> methods

15:14 chouser: jweiss: gen-class

15:14 joshua-choi: chouser: I see. That determines how the tree's nodes are labelled, right?

15:14 jweiss: chouser- does gen-class support annotations now?

15:14 chouser: jweiss: I believe so.

15:14 joshua-choi: yeah

15:14 joshua-choi: Okay, thanks.

15:14 jweiss: ok i'll try that

15:15 chouser: joshua-choi: len-meter is for looking things up by index.

15:15 oh

15:15 bye.

15:15 ohpauleez: haha'

15:27 amalloy: i'm using a sorted-set to store a group of cards for a card-game engine, and i was surprised to find that if i use remove instead of disj it's noticeably faster (arguably a bit broken since it turns my sets into seqs). any idea why this should be faster?

15:28 raek: amalloy: it might be due to remove being lazy

15:29 try putting a (doall ...) around it

15:29 if you want to measure the execution time

15:31 amalloy: raek: changed to (update-in hand [suit] #(doall (remove #{card} %))); is that what you mean? if so, it's still faster

15:31 raek: ,(time (dotimes [_ 1e5] (disj (sorted-set 1 2 3 4 5 6 7 8 9 10) 5)))

15:31 clojurebot: "Elapsed time: 3080.067 msecs"

15:31 raek: ,(time (dotimes [_ 1e5] (remove #{5} [1 2 3 4 5 6 7 8 9 10])))

15:31 clojurebot: "Elapsed time: 120.957 msecs"

15:32 raek: ,(time (dotimes [_ 1e5] (doall (remove #{5} [1 2 3 4 5 6 7 8 9 10]))))

15:32 clojurebot: "Elapsed time: 797.188 msecs"

15:32 chouser: amalloy: how large is your set?

15:32 amalloy: small

15:32 raek: remove does not compute anything until the sequence is realized

15:32 chouser: yeah, it's going to be mostly constants and overhead

15:33 amalloy: in real life it will be as large as like 7; on the data i'm using to test while i develop it's like 2

15:33 jweiss: are there issues with using gen-class in the REPL? user> (gen-class), and then (user.) throws ClassNotFound

15:33 raek: jweiss: yes, gen-class can only be used with ahead-of-time compilation

15:34 hrm, could one use (compile my.name.space) to do aot at the repl?

15:35 jweiss: raek: i just tried that

15:35 Could not locate user__init.class or user.clj on classpath:

15:35 i guess AOT is for clj files on disk only?

15:36 clojurebot: AOT genclass is http://paste.lisp.org/display/70665 and http://clojure-log.n01se.net/date/2008-11-18.html#14:19

15:36 raek: maybe the namespace name has to be quoted

15:36 jweiss: raek: i ran (compile 'user)

15:36 raek: do you have a user.clj file?

15:36 jweiss: raek: no - i'm at the REPL

15:37 only source files, I think

15:37 chouser: yeah

15:37 jweiss: ok, well, that'll work for my ultimate purpose, just makes it harder to play with :)

15:38 raek: gen-class is mainly for java interop where you need to compile java code that uses clojure code

15:38 ohpauleez: jweiss: lein interactive my make it easier

15:38 jweiss: raek: yeah, that is what i am doing - want to write testng tests in clojure

15:38 raek: proxy can be used for the java-in-clojure situation

15:38 jweiss: testng is a java lib that reads classes for @Test annotations on public methods, and runs them

15:39 raek: i don't think proxy supports annotations

15:39 i am not sure that gen-class does either :) but i'll try it

15:39 raek: there is some support for annotations in at least one of the interop constructs

15:39 since 1.1

15:42 tomoj: whoa

15:42 I never thought it would happen

15:43 raek: hrm, I'm uncertain about whether it was 1.1... it is there in 1.2 at least

15:46 Try loading that, then once its done, I'll keep a connection with conviva.com, I cant break it

15:46 Sorry, wrong chan :)

16:09 Sorry, wrong chan :)

16:10 jneira: hi people!

16:15 arkh: How would one make this work:

16:15 ,(every? #(0 <= % <= 255) [20 21 22])

16:15 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

16:15 joshua-choi: You want #(<= 0 % 255) I imagine

16:15 arkh: oh wow

16:16 *sheepish* thank you

16:16 joshua-choi: No problem

16:17 jneira: ,(let [t Object v 2] (with-meta {:value v} {:type t}))

16:17 clojurebot: Eval-in-box threw an exception:java.lang.StackOverflowError

16:17 jneira: jum

16:18 strange error

16:18 strange in my ignorance of course

16:20 chouser: seems strange to me

16:20 ,(with-meta {} {:type Object})

16:20 clojurebot: Eval-in-box threw an exception:java.lang.StackOverflowError

16:20 jneira: :type is only available on multimethods

16:20 chouser: no

16:21 jneira: ,*clojure-version*

16:21 clojurebot: {:interim true, :major 1, :minor 2, :incremental 0, :qualifier "master"}

16:21 jneira: jum

16:21 chouser: it's the printing of it that's blowing up.

16:22 Raynes: ,(clojure-version)

16:22 clojurebot: "1.2.0-master-SNAPSHOT"

16:22 jneira: yep in the sea of traces i saw something about print

16:22 chouser: ,(:value (with-meta {:value 2} {:type Object}))

16:22 clojurebot: 2

16:22 chouser: creating and using it is fine.

16:22 wwmorgan: ,(meta (with-meta {} {:type Object}))

16:22 clojurebot: {:type java.lang.Object}

16:22 jneira: ok

16:23 a bug then?

16:23 chouser: must be

16:29 weird

16:29 ,(print-method (with-meta {} {:type Object}) *out*)

16:29 clojurebot: java.lang.StackOverflowError

16:29 chouser: ,(#'clojure.core/print-meta (with-meta {} {:type Object}) *out*)

16:29 clojurebot: nil

16:30 chouser: ,(#'clojure.core/print-map (with-meta {} {:type Object}) #'clojure.core/pr-on *out*)

16:30 clojurebot: {}

16:30 chouser: the two things that print-method call work fine. but print-method overflows.

16:30 gotta run.

16:36 arkh: ,(int "10")

16:36 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character

16:36 arkh: : /

16:36 Raynes: -> (Integer/parseInt "10")

16:36 sexpbot: => 10

16:36 sexpbot: => 10

16:37 jneira: interesting trace exploring

16:38 ,(doc print-method)

16:38 clojurebot: "; "

16:38 arkh: thanks Raynes

16:41 jneira: thank chouser, do not know if i should open a ticket ...

16:41 arkh: hm - I still get a ClassCastException when trying to Number work on a String after read-string. Clojure should have its own (Integer/parseInt)

16:41 *to do

16:42 clojurebot: "([s]); Reads one object from the string s"

16:42 clojurebot: java.lang.Integer

16:43 arkh: : / ... k, nvm

16:43 Raynes: If your numbers are user input, you should use Integer/parseInt to avoid security issues.

16:43 arkh: good to know! They are user input

16:44 jneira: ,(do (defprotocol Monad (>>= [m f])) (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))

16:44 clojurebot: DENIED

16:44 Raynes: Can't def stuff.

16:44 jneira: eyyy

16:44 jeje no haskell stuff :-P

16:46 implement the constructor function return is more tricky

16:47 Chousuke: I wrote a toy monad implementation based on protocols once

16:47 It's in a gist somewhere

16:47 jneira: (let [proto (defprotocol Monad (>>= [m f]))] (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))n

16:48 ,(let [proto (defprotocol Monad (>>= [m f]))] (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))

16:48 clojurebot: DENIED

16:48 jneira: jum

16:48 Raynes: Seriously, you can't def stuff. :P

16:48 Chousuke: http://gist.github.com/312281 here.

16:48 jneira: interesting Chousuke

16:49 i am going to take a look

16:49 Chousuke: I still don't know how I managed to write the lift function

16:51 jneira: i have not reach this point ... i am trying to implement return with multimethods :-/

16:52 for learning, i really like macro acrobatics of clojure.contrib.monads, but too advamced for me :-P

16:56 dispatch on return type of functions is neat :-/

17:35 jjido: is the (last) function really slow on vectors?

17:37 wwmorgan: ,(time (last (vec (range 1000000))))

17:37 clojurebot: 999999

17:37 "Elapsed time: 1816.7 msecs"

17:37 jjido: I don't understand why a version that does (vec (cons)) is faster than one that doesn't

17:37 looks slow

17:38 wwmorgan: jjido: If you know that the collection you're working with is a vector, you should just use nth on count. That way you'll get O(1) performance instead of O(n)

17:39 jjido: ,(time (nth (vec (range 1000000)) 999999))

17:39 clojurebot: 999999

17:39 "Elapsed time: 1044.719 msecs"

17:39 jjido: ,(time (nth (vec (range 1000000)) 999999))

17:39 clojurebot: 999999

17:39 "Elapsed time: 1418.003 msecs"

17:39 jjido: mmh?

17:40 wwmorgan: ,(time (do (vec (range 1000000)) 0))

17:40 clojurebot: 0

17:40 "Elapsed time: 996.783 msecs"

17:40 jjido: ok

17:42 wwmorgan: ,(let [v (vec (range 1000000))] (time (last v)) (time (nth v (dec (count v)))))

17:42 clojurebot: 999999

17:42 "Elapsed time: 226.482 msecs" "Elapsed time: 0.05 msecs"

17:44 jjido: wow my algo is 5x faster now

17:45 wwmorgan: awesome :-)

17:47 jjido: I want to share it: http://pastebin.ca/1940906

17:47 Use as (merge-sort-cont unsorted-vector println)

17:51 arkh: ,(if (and (map #(= 1 %) [3 2 1])) true false)

17:51 clojurebot: true

17:51 arkh: ?

17:54 ninjudd: ,(if (some #(= 1 %) [3 2 1]) true false)

17:54 clojurebot: true

17:54 ninjudd: (if (every? #(= 1 %) [3 2 1]) true false)

17:55 ,(if (every? #(= 1 %) [3 2 1]) true false)

17:55 clojurebot: false

17:55 arkh: I can use every, though it seems like 'and' should work, too : /

17:56 'every?' looks better : )

17:56 jneira: ,,

17:59 joshua-choi: chouser: In your finger trees, what is the string-meter for?

17:59 chouser: debugging

18:00 it's transitive but not commutative, so if I mess up the order of ops len-meter will be correct, but string-meter will fail to match

18:02 amalloy: arkh: a seq always evaluates to true no matter what's in it

18:02 if you really prefer and to every (IMO yuck), try (apply and (map ...))

18:03 arkh: amalloy: cool - thank you for explaining it to me. Without knowing that it seemed really odd.

18:06 amalloy: welcome. look forward to being surprised by that every so often in the future

18:07 ,(if (filter zero? (range 10 20)) true false)

18:07 clojurebot: true

18:12 amalloy: how do i specify infinity? i see that Double/POSITIVE_INFINITY displays as Infinity, but entering Infinity at a prompt throws an exception

18:14 arkh: amalloy: it's kind of tricky, because (if (and (a b c)) true false) is entirely different from (if (and a b c) true false) and is easy to see. But if (a b c) is being returned by some function .. hmm ... maybe it's less tricky now that I know.

18:15 raek: ,(if (seq (filter zero? (range 10 20))) :truthy :non-truthy)

18:15 clojurebot: :non-truthy

18:16 amalloy: arkh: that's what apply is all about: expanding a list of arguments in order to call a function with its element instead of with itself

18:16 arkh: now I'm confused again : )

18:17 amalloy: arkh: (seq x) returns a sequence if x has elements, else nil

18:17 raek is just trying to confuse us

18:17 arkh: ,(if (and (seq (filter zero? (range 10 20)))) :truthy :non-truthy)

18:17 clojurebot: :non-truthy

18:17 amalloy: :)

18:18 ,[(filter zero? (range 10 20)) (seq (filter zero? (range 10 20)))]

18:18 clojurebot: [() nil]

18:18 arkh: evil!

18:19 amalloy: aw, i just realized i missed my chance to use juxt:

18:19 ,((juxt identity seq) (filter zero? (range 10 20)))

18:19 clojurebot: [() nil]

18:19 raek: seq is also used to force a lazy sequence to yield either nil or a cons (or any ISeq)

18:19 arkh: that seems like an unwanted inconsistency - but then I'm still learning

18:20 raek: if a function returning a lazy seq has to return nil if there are no elements, the first cons cell can never be fully lazy

18:21 amalloy: arkh: it's actually a consistency. it's much easier to remember that *anything* but nil or false is treated as logical false, than to try and remember some complex set of rules. it's also true that it messes with laziness, which may be the real reason, but i think it's not necessary to grasp that for a while

18:21 arkh: raek: that sounds like something Confucius would say

18:22 raek: a really really really lazy sequence: http://gist.github.com/480608

18:22 it's so lazy that it outsources the element generation to the user... :-)

18:23 amalloy: hah

18:23 raek: (ask-the-user-seq) returns a LazySeq object

18:23 when seq is called on it, a message box will show up and ask the user for a value

18:23 amalloy: really lazy sequences are more like (defn be-lazy [args] nil (comment TODO))

18:23 clojurebot: Why are you asking *him*

18:24 raek: if the user chooses cancel, (seq (ask-the-user-seq)) returns nil

18:25 so a LazySeq is like something that hasn't decided whether it's gonna be a cons or nil

18:25 therefore, nil-punning requires calling seq on it

18:26 arkh: nil-punning?

18:26 amalloy: see, you're filling his head with CL ideas, raek

18:27 arkh: laziness is like slow kung-fu or something - still learning it

18:27 raek: (if value ... ...) ; <-- nil-punning on 'value'

18:27 arkh: k

18:27 raek: to check whether it is something or not

18:27 amalloy: nil-punning is basically treating an empty seq as nil, which can be more convenient when you're recursively creating a sequence

18:28 raek: just remember that in Clojure, () is not nil, and () is also truthy

18:29 amalloy: (loop [a [1 2 3 4]] (prn a) (when a (recur (rest a)))) is an attempted nil-pun that won't work in clojure

18:30 the (when a) test will always be true, because even once a is empty it's still a sequence and therefore still true. if you instead used (when (seq a)), it would work

18:30 arkh: amalloy: I was just about to ask 'why', but that makes sense

18:30 raek: (loop [a (seq ...)] (prn a) (when a (recur (next a)))) would be the clojure way, (next x) = (seq (rest x))

18:31 amalloy: yes yes, but we're showing him how seqs work

18:31 raek: where ... is any (potentially empty) collection

18:32 arkh: so the recur to the top of the loop uses (seq) ?

18:32 when there are no more items in (next) ... is (seq) being called each recur?

18:33 raek: in my example, yes

18:33 grignaak: I have a large (IMO) function that is basically repeated around in 5 different places except for 5 'slots'. Is there an idiom (like "template method") I can use that doesn't require passing in an additional 5 fns into the algorithm?

18:33 raek: ,((juxt next rest) [1])

18:33 clojurebot: [nil ()]

18:34 raek: so the when will only get values that has passed throught seq

18:35 arkh: I didn't know values passed from recur to the top somehow had any original functions/verbs applied to them

18:36 amalloy: grignaak: what about something like this? (defn make-dostuff-fn [param1 param2] (fn [x] (do-stuff-with param1 (and param2))))

18:36 raek: arkh: there is no magic going on... seq is called because next calls it internally

18:37 (defn next [x] (seq (rest x)))

18:37 arkh: ok good - so no top-of-the-loop implied stuff

18:38 doh - I didn't catch the next vs. rest difference in the two examples

18:42 grignaak: amolloy: thanks. I guess I can specify common params with the {... :or {...} } context. not pretty, but I guess it's better than a lot of duplicate code :/

18:45 amalloy: yeah, if there are five things you might want to tune, it's hard to avoid having five parameters to something

18:52 grignaak: this is what it looks like now: http://pastie.org/1159426

18:53 dsantiago: arohner, are you around?

18:54 amalloy: grignaak: i don't feel up to diving through the whole thing, but you can replace (fn [& args] x) with (constantly x)

18:55 arohner: dsantiago: yeah, what's up?

18:55 grignaak: I guess I could also remove the peek and pop params if there is an implementation of a queue wrt peek/pop/conj

18:55 dsantiago: Ahrohner, hi, I was just enjoying using Scriptjure, and I was wondering if there was some way to do something like (. (getElement "myId") value).

18:56 Right now, that results in getElement('myId').value()

18:56 grignaak: (lists and vectors both act like stacks wrt peek/pop/conj)

18:56 arohner: dsantiago: that's what I would expect it to do

18:56 what do you want it to do?

18:57 dsantiago: Access the member called value.

18:57 arohner: use aget

18:58 dsantiago: Ah, OK, I thought that was for arrays only.

18:58 arohner: clojure's (.) uses introspection or the class's type to figure out whether value is a field or a function call. I don't want to write the code to do that in JS

18:58 amalloy: grignaak: check out http://tinyurl.com/22ps9cw - i don't know if it's any good, but it sounds like what you want

18:58 arohner: foo.bar and foo["bar"] are equivalent in JS

18:58 dsantiago: Oh no, I understand completely. My questions was more "Is there some way to access a member."

18:58 I see. Thank you.

19:00 grignaak: amalloy: yep, I'm using that for djikstra's/a*, and lists for dfs, I guess I could wrap it for dfs

19:01 *bfs (the second dfs)

19:14 mabes: what lib do people use to generate XML in clojure? I found prxml http://clojure.github.com/clojure-contrib/prxml-api.html Any other options or that the best option?

19:46 trengof: hi, I'm trying to "and" together a list of booleans, currently I have (reduce and (map a-boolean-test? a-vector))) which doesn't work as "and" is a macro, anyone got some pointers?

19:46 amalloy: ,(apply and [true false])

19:46 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/and

19:46 amalloy: boo

19:46 chouser: trengof: take a look at 'every?'

19:47 trengof: amalloy: since map returns a list that doesn't work

19:48 doesn't work with vectors either hmm

19:48 amalloy: no, it doesn't work because and is a macro :P. apply turns the list into real args

19:49 chouser is right that every? is the right answer, but you could do it with an anonymous function too

19:49 trengof: yeah thanks, i'm looking at every? now

19:50 chouser: trengof: you might also want 'identity'

19:51 amalloy: ,(every? identity [2 false])

19:51 clojurebot: false

19:51 amalloy: ,(every? identity [2 true])

19:51 clojurebot: true

19:52 chouser: that's not quite like 'and', which returns the the first falsey value.

19:52 trengof: much simpler: (reduce and (map a-boolean-test? a-vector))) -> (every? a-boolen-test? a-vector)

19:52 chouser: but one hardly ever cares.

19:53 amalloy: yeah, it's rare to care whether your test failed because of a false or a null

19:54 chouser: ,(first (remove identity [1 nil]))

19:54 clojurebot: nil

19:54 chouser: ^^^ just in case. ;-)

19:54 amalloy: chouser, that's sick

19:58 chouser: by the way, are you still taking suggestions on the manning forums? i posted something ages ago about chapter 10.4 but no responses

19:59 chouser: amalloy: sorry for not responding. I'm not sure if we've missed the window for changes in this edition or not.

20:04 amalloy: np. if it goes to print this way i'll show off to everyone how much smarter than the authors i am :)

20:04 chouser: :-)

20:05 joshua-choi: chouser: Finger tree question. What's the intended function of string-meter?

20:05 chouser: testing and debugging

20:05 joshua-choi: it's transitive but not commutative, so if I mess up the order of ops len-meter will be correct, but string-meter will fail to match

20:06 joshua-choi: Okay, thanks

20:07 ,(hash {})

20:07 clojurebot: 0

20:07 joshua-choi: ,(hash [])

20:07 clojurebot: 1

20:07 joshua-choi: ,(hash {:a 3, :b 2})

20:07 clojurebot: 2027821080

20:08 joshua-choi: chouser: I wonder if you could refer to a specific node, regardless of its position in the sequence, if you use hash codes and some appropriate measure and meter.

20:08 chouser: hm, going to sort your finger tree by hash?

20:08 oh, not sort by hash?

20:09 joshua-choi: A finger tree that sorts by insertion position but also can look up nodes by hash...

20:10 Eh, I don't know. But I need to be able to refer to nodes.

20:10 I want to create a text piece table in Clojure: http://www.cs.unm.edu/~crowley/papers/sds.pdf

20:11 chouser: joshua-choi: gotta go, but I will ponder your question.

20:11 Thansk

20:11 chouser: I can't say I'm hopeful, but mayber there's some clever trick...

20:11 joshua-choi: Take a look at that paper.

20:11 It's very easy.

20:11 Pay attention to the piece table section.

20:11 Ciao

21:39 seangrove: ,(doc clojure.contrib.string/take)

21:39 clojurebot: "([n s]); Take first n characters from s, up to the length of s."

21:40 seangrove: ,(clojure.contrib.string/take 5 "this is a test")

21:40 clojurebot: "this "

21:42 seangrove: ,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (take length (second (clojure.contrib.string.split #":" item))))

21:42 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.string.split

21:42 seangrove: ,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (take length (second (clojure.contrib.string/split #":" item))))

21:42 clojurebot: (\s \p \a \m)

21:42 seangrove: Hrm

21:42 ah

21:42 Not string/take

21:42 ,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (clojure.contrib.string/take length (second (clojure.contrib.string/split #":" item))))

21:42 clojurebot: "spam"

21:42 seangrove: Yup

21:50 ,["a" 50 "b" 60"]

21:50 clojurebot: EOF while reading string

21:50 seangrove: ,["a" 50 "b" 60]

21:50 clojurebot: ["a" 50 "b" 60]

21:50 seangrove: Quite right clojurebot

21:51 ,(for [key ["a" 50 "b" 60]] (print key))

21:51 clojurebot: (nil nil nil nil)

21:51 seangrove: ,(for [[key val] ["a" 50 "b" 60]] (print (str key ":" val)))

21:51 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

21:51 seangrove: Nope

21:52 Don't think I have this destructuring thing down :P

21:52 I'm actually trying to turn ["a" 50 "b" 60] into {:a 50 :b 60}

21:54 Think I might have it...

21:54 ,(apply hash-map ["a" 50 "b" 60])

21:54 clojurebot: {"a" 50, "b" 60}

21:55 seangrove: Close... but not sure how to call (keyword) on "a" and "b" there

21:55 lancepantz: there is a keywordize keys fn in contrib

21:56 or for

21:56 seangrove: ,(clojure.walk/keywordize-keys (apply hash-map ["a" 50 "b" 60]))

21:56 clojurebot: java.lang.ClassNotFoundException: clojure.walk

21:57 seangrove: for would probably work.. just feels like I'm missing something elegant here

21:58 lancepantz: ,(into {} (for [[k v] (partition 2 ["a" 50 "b" 60])] [(keyword k) v]))

21:58 clojurebot: {:a 50, :b 60}

21:59 lancepantz: that's probably not the most elegant however

22:00 seangrove: this says that keywordize-keys was added in clojure 1.1? http://richhickey.github.com/clojure/clojure.walk-api.html

22:01 lancepantz: yeah, what you had earlier should work on a repl

22:01 i'm not how to use fn's outside of core with clojurebot

22:03 seangrove: thanks :)

22:21 ,(println (clojure.contrib.string/join "" (butlast (string/partition #"e" "li1ei40e4:seane")))))

22:21 clojurebot: java.lang.Exception: No such namespace: string

22:21 seangrove: ,(println (clojure.contrib.string/join "" (butlast (clojure.contrib.string/partition #"e" "li1ei40e4:seane")))))

22:21 clojurebot: li1ei40e4:sean

22:21 seangrove: Any more elegant way to do that?

22:24 lancepantz: ,(.substring "li1ei40e4:seane" 0 -1)

22:24 clojurebot: java.lang.StringIndexOutOfBoundsException: String index out of range: -1

22:24 lancepantz: blah, damn java

22:26 ,(let [s "li1ei40e4:seane"] (.substring s 0 (dec (.length s))))

22:26 clojurebot: "li1ei40e4:sean"

22:27 seangrove: Hmm, I think that might work..

22:27 Certainly more legible than what I have :P

22:27 lancepantz: i usually end up using String directly instead of contrib.string

22:28 ,(let [s "li1ei40e4:seane"] (.substring s 0 (dec (count s))))

22:28 clojurebot: "li1ei40e4:sean"

23:28 cinim0d: clojurebot: doc def. needs example for all those useful core functions.

23:28 clojurebot: the doctor is out

23:29 cinim0d: mm

23:29 s/clojurebot:/clojure

Logging service provided by n01se.net