#clojure logs

2010-09-14

00:52bhenrywhat is the reason that + can take 0 args but - cannot?
00:53wwmorganbhenry: - can take a difference, or an opposite. Neither a difference nor an opposite is well-defined for 0 arguments
00:54bhenrysum of 0 args is 0, so opposite of 0 args can't be zero?
00:55bhenry,(- 0)
00:55clojurebot0
00:56tomojis it because they're not commutative?
00:56tomojthey being - and /
00:56KirinDavetomoj: I've heard that justification.
00:58wwmorganit'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"
00:59tomojwhereas with (-) you'd need a particular purple giraffe to go first?
01:01wwmorganYeah I don't see why (-) would be 0 and not 7 or pi or something
01:02tomoj(+ 1) (+ 1 2) vs (- 1) (- 1 2)
01:07bhenryhttp://mathforum.org/library/drmath/view/52387.html
01:08cemerickKirinDave: did you notice the clojure-colfusion crowd building? That's sure to be the *fourth* audience ;-) http://search.twitter.com/search?q=clojure+coldfusion
01:08KirinDavewait wut?
01:08cemerickshit you not
01:09KirinDave"whats this i dont even"
01:10tomoj"Obviously, there is no answer; that is, x = {}." uhhwhat?
01:11cemerickbhenry: what's funny about that is that the guy asking the question is probably *the* Alistair Cockburn.
01:12wwmorganhe's mixing notation. He should say that for 5 + x = 3 + 2, x = {0} is the answer
01:12bhenrytomoj if there is no answer the answer is not zero, there is an empty set of answers
01:12wwmorgansimilarly, if x * x = 4, then x = {-2, 2}
01:13jcromartiei am a coldfusion developer and what is this
01:13cemerickjcromartie: I'm starting to think there's a small army of you CFML folks out there.
01:14jcromartieI'm kidding. Dear god no.
01:14jcromartieI did my time with CFML.
01:14cemerickah, oh well
01:14jcromartiebut now I stay as far away as possible
01:14bhenryhttp://github.com/seancorfield/cfmljure has 5 watchers. not quite an army
01:14jcromartiehttp://www.urbandictionary.com/define.php?term=I'm%2012%20years%20old%20and%20what%20is%20this%3F
01:15tomojmy time was a couple weeks, which was far too long
01:15cemerickbhenry: I suspect that a vanishingly small minority of CF guys are even aware of git, nevermind watching a CF/clojure project. :-)
01:16bhenryhaha touche
01:17bhenrydoes myspace still use cf? they must have a team of at least three.
01:19cemerickWe'll have to have a poetry slam at the conj.
01:45brianstamandwhen 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)
01:45brianstamandAnyone know what I'm doing wrong?
01:46tomojmaybe try installing rlwrap?
01:47tomojstrange thing is I have no rlwrap on my path and `lein repl` works fine
01:47brianstamandI 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
01:48brianstamandwell anyway it works now that I installed rlwrap lol
01:48brianstamandthanks
01:49wwmorganleiningen falls over to jline if rlwrap isn't installed
01:49wwmorganit appears your leiningen thought rlwrap was installed when it wasn't
01:59tomojlooks like the error is coming from which
01:59cgrandmorning clojure people!
01:59tomojmaybe which on fedora behaves differently?
02:04brianstamandmorning cgrand
02:04brianstamandtomoj, I have no idea, but I do know that yum install rlwrap seemed to make the error message go away :P
02:06tomojbrianstamand: what does `which frobniz` do for you?
02:06wwmorganbrianstamand: was there another error message when 'lein repl' failed, after the which line?
02:09brianstamandtomoj: /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)
02:10brianstamandwwmorgan: no, just "REPL started; server listening on localhost:55668." which i dont think is an error msg :)
02:11wwmorganbrianstamand: oh. Did you try to connect to the repl server? I suspect everything would have worked?
02:11brianstamandthe repl didn't actually fail it just spit out the first error message, and then wouldnt run any command right
02:12brianstamandhow do you connect to the repl server? I'm brand new to this sorry :)
02:12wwmorganoh sorry, I just mean that the repl started up
02:12brianstamandyeah the repl seemed to work
02:12brianstamandwhat I've been trying to do is get compojure running actually, and to make compojure work I installed lein
02:13wwmorganaha. I'm pretty sure I know what's going on. I'll submit a fix to leiningen
02:14brianstamandcool
02:14wwmorganas far as getting compojure running, that's a mostly painless process
02:23brianstamandya compojure seems to be running properly, from the repl, but i haven't been able to see the Hello World thing for some reason
02:24brianstamandok it's working now. Thanks for the help :) I always learn something when I come to this channel :)
02:42sandGorgonhi 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 ?
02:45notsonerdysunnyis it possible to find out if a "promise" has been "deliver"ed without blocking? a simple "deref" would block it...
02:45seangroveHey all, I'm trying to play around with creating a dsl http://pastie.org/1157591
02:45seangroveYou can see it's not quite right
02:46seangroveShould I start using macros here... should I be rethinking the sub-exps stuff...
02:48G0SUBgrinnbearit
02:50grinnbearithey
02:51wwmorganseangrove: 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
02:54wwmorgannotsonerdysunny: 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
02:54clojurebothiredmans euler.clj is so embarassing
02:56seangrovewwmorgan: I'll give that a try :0
02:56notsonerdysunnywwmorgan: .. hmm.. that would be very nice to have ..
03:04wwmorgannotsonerdysunny: I agree. futures, for example, have something analogous in future-done?
03:07notsonerdysunnywwmorgan: yea true
03:20notsonerdysunnywwmorgan: I think this behaviour is purposefull.. since it will break the functional-programming paradigm..
03:21notsonerdysunnycode becomes time dependend...
03:21notsonerdysunny*dependent
03:21notsonerdysunnysorry .. I am myself not convinced with what I just said..
03:21wwmorgannotsonerdysunny: I don't see a problem with it
03:23notsonerdysunnywwmorgan: 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...
03:26wwmorgannotsonerdysunny: can you show me a code example?
03:35notsonerdysunny(let [s (promise)] s)
03:35notsonerdysunnywwmorgan: *
03:36notsonerdysunny,(let [s (promise)] s)
03:36clojurebotnotsonerdysunny: Excuse me?
03:36notsonerdysunny->(let [s (promise)] s)
03:36sexpbotjava.lang.SecurityException: Code did not pass sandbox guidelines: (#'clojure.core/promise)
03:40wwmorgannotsonerdysunny: you'll notice that (promise) also blocks
03:41wwmorganbut not (if (promise) 0 1)
03:41wwmorganthe 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
03:44notsonerdysunnywwmorgan: you may be interested in the replies I got from the google clojure group
03:45notsonerdysunnyhttp://groups.google.com/group/clojure/browse_thread/thread/369f1cbf16fcbf94
03:47seangroveI can't seem to get this clojure right.. http://pastie.org/1157645
03:47seangrovefor some reason it doesn't seem to be extrcting "something" from the array
03:49amalloyyou need sub-exps#, don't you? it always shouts at me if i try to do that
03:49seangroveAh, that may be it
03:49seangroveI'm not sure where that's documented though
03:49wwmorganseangrove: there are at least two other things wrong
03:50amalloyit's documented in the docs for syntax-quote, somewhere
03:50amalloy,(doc `)
03:50clojurebotUnmatched delimiter: )
03:50amalloyaww
03:50amalloy,(doc syntax-quote)
03:50clojurebotI don't understand.
03:50wwmorganthe macro definition appears to expect a single symbol for an argument, but you're passing it a vector with a symbol in it
03:51seangrovewwmorgan: You're right :(
03:52seangroveThank you... that looks a bit better
03:52wwmorganand, actually, I think it might just work with that change and amalloy's
03:52amalloyit gets close
03:53seangroveWhy do I need sub-exps# ?
03:53seangroveFor understanding's sake, of course :)
03:53amalloymacros aren't allowed to declare variables "for" the code they expand into
03:54amalloysub-exps# expands into a gensym which is guaranteed to be a unique variable name
03:54seangroveAh, I see
03:54seangroveInteresting
03:54seangroveWhy aren't they allowed to do that?
03:54amalloyotherwise you could accidentally shadow a variable
03:55amalloysee http://www.gigamonkeys.com/book/macros-defining-your-own.html where it talks about leaky abstractions
03:55amalloythe 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
03:56amalloybecause 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
03:56seangroveI thought it might be something like that, but it doesn't seem like such a big deal
03:57seangroveProbably worse for those who've been bitten by it :)
03:57LauJensenIn Clojure its not a big deal
03:57LauJensenIn CL it is
03:57LauJensenIn 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
03:58LauJensen,`x
03:58clojurebotsandbox/x
03:58LauJensen,`#'x
03:58clojurebot(var sandbox/x)
03:58wwmorganseangrove: I took a shot at it here http://pastie.org/1157661
03:58amalloyyes. 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
03:58wwmorgannotice that ~name became '~name
03:59seangroveOh, interesting
03:59seangroveI have this: http://pastie.org/1157664
03:59seangroveI think that may be my problem :)
03:59amalloyyep
04:00amalloyi usually still have to poke around at ~' and '~ and all this nonsense for a while before i remember how they work
04:00seangroveAnd does , do anything like it does in scheme?
04:01amalloyno
04:01amalloyit's whitespace
04:01amalloy,[1, 2,,,,,,,,,,,,,,,,,,,,,,,,,3]
04:01clojurebot[1 2 3]
04:02seangroveok
04:02seangroveSo in macros, the special characters are `'~#
04:02seangrove4?
04:03amalloywell that's...a simplification, but those are the characters that might behave differently than you think in macros
04:03clojurebotBarking spiders!
04:03wwmorgan' is just quote, inside or outside of a macro
04:03wwmorganalso ~@
04:04amalloyand ` is "just" syntax-quote inside or outside a macro, but it's unusual to want to use it outside one
04:04LauJensenseangrove: ` 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
04:04amalloy,(let [arg 'wooo-symbol] `(println ~arg))
04:04clojurebot(clojure.core/println wooo-symbol)
04:05seangroveAh, awesome
04:05seangroveThanks, I think that's really useful
04:05amalloyuse your powers for good
04:06seangroveHey now... No promises
04:07LauJensen(defmacro with-trouble [& body] `(let [~'x 5] ~@body))
04:07LauJensen#'user/with-trouble
04:07LauJensenuser=> (let [x 100] (with-trouble (+ x 5)))
04:07LauJensen10
04:07LauJensenThats how hard it is, to get into trouble :)
04:10seangroveNice!
04:10amalloyLaujensen! now i'm going to have nightmares!
04:11LauJensenhehe
04:11LauJensenRich makes you work hard to have bugs
04:11amalloyto be fair, the debug support, even with swank, makes me work hard to fix them too
04:13LauJensenhehe, true - its to teach you the lesson of not introducing bugs
04:14LauJensenAnd actually, stacktraces have just been improved in master with the pst function, so you get more accurate details
04:14amalloyspeaking of which, who's in charge of slime/swank for clojure? i can reproducibly crash emacs
04:14seangroveI can't use a macro with do-seq, can I?
04:15LauJensenamalloy: I don't know, I'd love to know though. We should ask technomancy!
04:15LauJensen$mail technomancy Who's maintaining slime/swank for Clojure?
04:15sexpbotMessage saved.
04:15LauJensenseangrove: no, but I think it will work with doseq
04:17amalloyheh. yes, doseq will work, but map won't
04:17seangroveheh
04:17seangrovehttp://pastie.org/1157686
04:17seangroveAh, I'm using a list, not a vector
04:17seangroveGot it
04:18amalloyalso i don't think you're using doseq right
04:18LauJensen(doseq [t tags] (make-tag t))
04:18amalloythat
04:18amalloyer wait
04:19amalloythere was just a discussion on the google group about why that won't work
04:19LauJensenWould 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
04:20tomojand how do you refer to the item?
04:20tomojwith % ?
04:20amalloyseangrove: you'll want to look at http://groups.google.com/group/clojure/browse_thread/thread/c2ba98e830c90d88 eventually if you want your make-tag to work
04:20LauJensentomoj: nothing, just wrap the functions in partial
04:21LauJensen(doit! coll my-fn)
04:22tomoj(comp dorun map) ?
04:22seangroveAh, yes, the macros are compile-time, not runtime...
04:22amalloybut you can pass them as literals, since the list of legal HTML tags is unlikely to change very often
04:22LauJensentomoj: doseq is less demanding on the system
04:24seangroveNot sure how I would pass them in as literals - the macros are expanded literally in-place, right?
04:25tomojLauJensen: only because it doesn't have to call your function, right?
04:25seangroveI could re-write make-tag so that it took a list of tags to make and used doseq there
04:25amalloyright
04:26tomojI mean, if the 'body' for doit! is passed as a function, you can't macroexpand the body out like you can with doseq, right?
04:26LauJensentomoj: map allocations a new sequence which doseq doesn't IIRC
04:26LauJensens/allocations/allocates/
04:26sexpbot<LauJensen> tomoj: map allocates a new sequence which doseq doesn't IIRC
04:26tomojright, doseq expands to a loop/recur over the seq, chunking
04:26amalloybetter would be to leave make-tag alone (or turn it into a function instead of macro) and add make-tags that takes a seq
04:27LauJensenonly use functions if you must control evaluation of the arguments
04:27LauJensenthen and only then, will I allow it
04:27amalloyer, only use macros?
04:27LauJensenyea
04:27LauJensen:)
04:28seangroveamalloy: 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?
04:28tomojaha
04:29tomojdo you only have the names for the vars at runtime?
04:29tomojif so, how would you pass them to defn without a macro?
04:30seangroveNo, they're available ahead of time
04:30tomojok
04:30seangroveDoesn't look like I can do it with defn... at least not in a way that jumps out at me immediately
04:31amalloyyou can do something like this:
04:31amalloy(defn gimme-code [a] `(println ~a))
04:31amalloy(defmacro write-stuff [& stuff]
04:31amalloy `(do
04:31amalloy ~@(map gimme-code stuff)))
04:31tomojI was thinking you wouldn't get line numbers and file information on defns done inside a function, but you do
04:32amalloyie, 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
04:32seangroveamalloy: So the defn is only for the body of the function?
04:33amalloyuser=> (macroexpand '(write-stuff 10 11))
04:33amalloy(do (clojure.core/println 10) (clojure.core/println 11))
04:33tomojthat is kinda neat
04:33tomojthen you can just call the functions to test parts of your macro
04:34amalloyit'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
04:34tomojyeah, I think macro-utility functions are a lisper thing?
04:34tomojsupport code for code generation
04:34amalloytomoj: not sure what you mean by a lisper thing?
04:35tomojI mean, if you are a wise lisper and have attained homoiconicity enlightenment, you have probably used this technique
04:36amalloyah. well i haven't really reached enlightenment yet, but i'm good at noticing the fiddly bits
04:36tomojbut I wouldn't know, rich hickey is a western guru and I have hardly begun on the path to lisp nirvana
04:37amalloyooc i don't suppose we have any bridge players in here?
04:37tomoj'ooc'?
04:38amalloyout of curiosity. i can never tell which abbrevs will be recognized where
04:38tomojah
04:38amalloyi figured with ymmv practically an icon of irc, i could get away with ooc here :P
04:38tomojI 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
04:38amalloysome days it seems that way...:)
04:39amalloybut then i discover ingenious ways to use the language built-ins and all is well
04:39jjidohow do I change a list-building recursive call into a (recur)?
04:40jjidoI have this in merge-sorted-lists-rec: (cons x1 (merge-sorted-lists-rec (rest a1) a2))
04:40seangroveDoesn't seem quite right :P http://pastie.org/1157700
04:41amalloyjjido: add a parameter to hold the current result list, and cons onto it before recurring
04:41amalloyseangrove: (macroexpand '(stuff)), not (macroexpand (stuff))
04:42tomojseangrove: 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
04:43seangroveYup, emacs
04:43amalloyand also you have to pass the list literally, in place, without a def: (macroexpand '(make-tags [a abbr address]))
04:43seangroveamalloy: Just came across that epiphany now :)
04:44tomojseangrove: if you have it set up for clojure, put point on the first paren in a macro call, and hit C-c C-m
04:44seangroveI'm in clojure mode, but I get "C-c RET is undefined"
04:46taliosEvening
04:46amalloytomoj: neat! that is super-handy
04:46tomojseangrove: you need slime set up
04:46tomojit can't macroexpand without talking to clojure
04:46amalloytomoj: i'm a bit sad that point has to be *exactly* on (before, if you use | caret instead of block) the first paren, though
04:47LauJensentomoj: I didn't know about that one, thanks
04:47tomojyes
04:47taliosgah - "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 :(
04:48amalloyugh, 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
04:49seangroveamalloy: Doesn't quite expand correctly I think, still just putting it in literally: http://pastie.org/1157705
04:49tomojamalloy: hmm
04:49seangrovetomoj: Thanks, I'll check it out when I turn slime back on :)
04:49tomojamalloy: my output looks like this https://gist.github.com/00c6fe4818b1722a27c6
04:49tomojif yours is uglier, try upgrading to swank-clojure 1.3.0-SNAPSHOT
04:50tomoj(that's (for [x [1 2 3]] (* x x)), btw)
04:50amalloyseangrove: that's weird. your code looks about right to me. i'll poke around at it
04:51tomojthe case of doit! brings up an interesting question for me
04:52tomojwould it be a good thing to be able to easily create macros which expand to loop/recur iteration over chunked sequences?
04:52tomojor is having the set of primitives which deal with chunked seqs nicely and building things out of them enough?
04:52seangroveI 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
04:53seangroveIs that right?
04:53seangroveAnd have I been missing that aspect all along with image-based development?
04:54amalloyseangrove: don't pass your list of tags as a vector, pass it raw. OR, take the & out of make-tags
04:54tomojapparently some scala work has been done with serializable continuations http://www.scala-lang.org/node/3485
04:55tomojmy 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
04:55seangroveamalloy: Yup, that was it, I think
04:55tomojbut smalltalk can serialize them according to some hn comment
04:55amalloyseangrove: i know! i had to try it out myself before i was confident enough to claim to have the answer :)
04:56tomojunfortunately we don't have decent continuations in clojure
04:56LauJensentomoj: 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
04:56LauJensen(clojure's first year)
04:57tomoj"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"
04:57tomojbuh-what?
04:57tomojif someone cracks your serialization scheme, don't they get to execute arbitrary code?? :O
04:58amalloytomoj: no clojure programmers would ever do anything evil. don't be silly
04:58greghall the server has to do is sign the data held by the client
04:58gregh(and verify the signature)
04:59tomojok
04:59tomojI thought there might be some cryptographic solution
04:59greghyeah, signing. :)
04:59greghit can be as simple as hash(data+secret)
05:02brianstamand(hash data secret) ? :P
05:02brianstamand(hash (+ data secret)) ? :P
05:02tomojhmac better I guess
05:04greghtouche, brianstamand :)
05:08amalloyokay, night folks
05:08LauJensen nighty night
05:08seangroveThanks again amalloy
05:09amalloynp seangrove. see you around
05:09amalloyit's a blast to be the one on the helping side for a change
05:24jjidois 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?
05:25LauJensenjjido: Use a vector + conj, thats the fastest
05:25tomojthe latter, but are you sure you want a list?
05:25tomojyeah
05:26LauJensen,(time (dotimes [_ 1e6] (conj [1 2 3] 4)))
05:26clojurebot"Elapsed time: 361.497 msecs"
05:26LauJensen,(time (dotimes [_ 1e6] (reverse (cons 4 '(1 2 3)))))
05:27clojurebot"Elapsed time: 2023.508 msecs"
05:41tomoja bit unfair I think
05:41tomoj,(time (do (reduce conj [] (range 2e6)) nil))
05:41clojurebot"Elapsed time: 3708.875 msecs"
05:41tomoj,(time (do (reverse (reduce conj () (range 2e6))) nil))
05:41clojurebotjava.lang.OutOfMemoryError: Java heap space
05:41tomojdarn
05:41tomoj,(time (do (reverse (reduce conj () (range 1e6))) nil))
05:41clojurebot"Elapsed time: 4790.578 msecs"
05:42tomoj,(time (do (reduce conj [] (range 1e6)) nil))
05:42clojurebot"Elapsed time: 1622.785 msecs"
05:42LauJensenI don't think its unfair. Most decisions between lists and vectors are based on where you want to append.
05:42LauJensenDoing it one way then reversion is just a sign that you've picked the wrong data structure
05:42tomojI mean it's really more like 3x slower, not 5.6x slower
05:42tomojstill much slower :)
05:43jjidohow do I make a vector from take, drop, rest and concat operations?
05:43tomojin linear time
05:43raek,(vec (list 1 2 3)) ; linear time
05:43clojurebot[1 2 3]
05:43LauJensenjjido: look at subvec and rseq, and see if you can model around them
05:43mrBlissor (into [] (take ..
05:44LauJensenThey are O(1) IIRC
05:44LauJensen,(doc subvec)
05:44clojurebot"([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."
05:44tomojyou can peek and pop vectors
05:44LauJensen,(doc rseq)
05:44clojurebot"([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"
05:44LauJensen,(doc peek)
05:44clojurebot"([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."
05:44LauJensen,(doc pop)
05:44clojurebot"([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."
05:46tomojjjido: you might get better advice asking about what you're actually trying to do
05:46jjidoI am just coding a merge sort, learning experience
05:48jjidotomoj: that is my current code http://pastebin.ca/1940405
05:53raekI'd suggest to use either vector operations or sequence functions, but not both
05:53raekcurrently, it contains no vector-specific code and yields a sorted sequential view of any collection
05:54raeka vector-only version might be more performant, but less general
05:54LauJensenraek: sequence functions for a tight loop in a fn like that?
06:02jjidois this better? http://pastebin.ca/1940413
06:03raekalso, the indentation is a bit misleading
06:05jjidosorry. I wrote it as if ... else if ... originally, then rewrote in Clojure. I can fix that
06:06raekI pasted it into emacs, selected it, pressed tab and put it back into pastebin: http://pastebin.ca/1940416
06:06jjidothe new version seems faster
06:06LauJensenjjido: should be a lot faster, try doing a million repeats (1e6) and timing both the old and the new
06:08raekwould it be faster if one did the vec call only on the final result, and not in every merge step?
06:08jjidoraek: the vec call is only when one list is empty
06:09jjido(vec (concat b a2)) -> both b and a2 are vectors
06:10jjidoand a2 should (usually) be small
06:10raekoh, right.
06:12raekalso, nested ifs like (if p1 e1 (if p2 e2 e3)) can be written with cond: (cond p1 e1 p2 e2 :else e3)
06:14mrBlissI translated the pseudo code mergesort from wikipedia into my own clojure version: http://gist.github.com/578831
06:21jjidomrBliss: mine's slightly faster on my computer, but yours is shorter :)
06:22mrBlissI've added a version of my mergesort optimized for vectors, it's a bit faster http://gist.github.com/578831#file_gistfile1.clj
06:23mrBlissmine is two times shorter than the pseudocode version on wikipedia :)
06:25jjidoit is a winner
06:28mrBlissstill 6 times slower than clojure.core/sort, but that's actually Arrays.sort
06:28jjidowhat is the difference between (/) and (quot)?
06:28LauJensen,(/ 5 2)
06:28clojurebot5/2
06:28LauJensen,(quot 5 2)
06:28clojurebot2
06:29jjidook using quot makes my algo a little faster
06:29bozhidarquot returns only the fixnum part of the division
06:29LauJensen,(doc case)
06:29clojurebot"([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
06:29LauJensencase is faster than if/cond IIRC
06:30mrBlisscase handles 1 expression, but we need 2 (left and right)
06:35mrBlissapparently (= 0 (count coll)) is slightly faster than (empty? coll)
06:35LauJensenmrBliss: empty? calls seq, where count is just reading a field
06:36mrBlissfigured that out after slime-edit-definition on empty? :)
06:37LauJensenpartly
06:37LauJensenYou'd also want to run an slime-inspector on any collection to see the count field
06:37mrBlissjjido: your version is slightly faster on my machine
06:38jjidoI could use case in merge-sort-rec, but does it have a default clause?
06:40jjidook I just need to omit the condition
06:41LauJensen,(case nil true "even" false "odd" "neither")
06:41clojurebot"neither"
06:41jjidonot faster.
06:41LauJensen,(case (even? 2) true "even" false "odd" "neither")
06:41clojurebot"even"
06:48mrBlissI give up: http://gist.github.com/578831#file_gistfile2.clj Just a bit faster
06:50LauJensenlooks good
06:58fbru02what'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 ...
06:59LauJensen,(5 {5 6 7 8})
06:59clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
06:59LauJensenfbru02: Its always a case of you putting an Integer in the position of a callable, ie. first place in a list
06:59LauJensen,({5 6 7 8} 5)
06:59clojurebot6
07:01fbru02LauJensen: thanks
07:02LauJensennp
07:19octein clojure projects, is it correct to use the same package as a namespace as you'd use with java?
07:19octelike com.example.myproject
07:19octeor just myproject directly?
07:21rhudsonYes, that's a reasonable naming scheme for namespaces
07:22LauJensenocte: Don't just one a single name like 'myproject'
07:25fbru02hey 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
07:26fbru02the question is what should i be giving as an input ? a vector of coeficientes ? and as output a partial function?
07:26LauJensenfbru02: macros are for controlling evaluation
07:28rhudsonI'd say the first step is to write a function that takes a vector of coefficients and a value.
07:28fliebelWhat was the channel for cake? More troubles on my side...
07:29fbru02rhudson: what is the value for ?
07:29rhudsonThat's the x
07:30fbru02rhudson: ah nono, but i want to return a lambda (fn (x))
07:31rhudsonWell, write the evaluation function first, then there's various techniques (e.g. partial) to give you a function of x
07:32rhudsonGiven (poly coeffs x), you can for instance (defn fpoly [coeffs] (fn [x] (poly coeffs x))
07:32LauJensenfliebel: #cake.clj ?
07:33fbru02rhudson: thanks, so basically what's the step for going from defn to defmacro:?
07:33rhudsonWell, why do you need a macro?
07:33fliebelLauJensen: jep :)
07:34rhudsonfbru02, as a general rule, if you can do something with functions, you shouldn't bother with macros
07:37fbru02rhudson: 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?
07:41rhudsonGiven that fpoly function as above, (defn make-linear [a] (fpoly [a]))
07:41rhudson(defn quadratic [a0 a1] (fpoly [a0 a1])) etc
07:46fbru02rhudson: good idea i will try it out
07:47bartjI rarely ever use partial, and I find it odd
07:47bartjcan anyone give a practical use case which forces me to use it?
07:47rhudsonbartj, I don't like it much myself
07:48LauJensenbartj: 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
07:48fliebelbartj: Some cases where you'd use an anonymous function, a partial fits better. It is also useful for making several similar functions.
07:49bartjfliebel, when I think of similar functions, I think of closures :)
07:49bartjfliebel, am I wrong
07:50fliebelbartj: Both are higher order functions. In simple cases, partial might be… simpler.
07:51bartjLauJensen, that seems like a nice example, thanks!
07:55bartjfliebel, now that you mention it, partial seems more "cleaner" (?) than anonymous functions, imo
07:55bartjfliebel, I never thought of it that way
07:56fliebelbartj: I use them all the time in Python, because the lack of proper lambdas.
07:58bartjfliebel, I didn't know Python had partial :)
07:59bartjfliebel, I also feel Python doesn't enforce "functional" thinking in the same way Clojure does - but, that is a topic for another day
07:59rhudsonThe relative advantage of anon funcs is that it's manifest how many args need to be supplied
08:00fliebelbartj: It's in functools. It doesn't enforce it at all, but Clojure does effect my Python style.
08:00bartjalso, I am always a bit nonplussed re: anonymous functions vs. functions
08:01bartjcurrently, if a function is very tiny (one or two statments) and is not called from multiple other functions, I make it anonymous
08:01bartjfliebel, yes, just looked it up here - http://docs.python.org/library/functools.html
08:57fliebelstephyn: set?
08:58rhudson,(doc vector?)
08:58clojurebot"([x]); Return true if x implements IPersistentVector"
08:58rhudson& (count v) gives you the size
08:58stephynI 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.
08:59rhudsonThen you have to search through the vector, one way or another.
09:00cinim0dhttp://richhickey.github.com/clojure-contrib/seq-utils-api.html -- Check for find-first
09:01rhudsonsorry, missed that you said "value is IN a vector"
09:01tomojhuh, deftypes don't get docstrings?
09:02tomojvectors will be no help
09:03tomojunless they're sorted vectors
09:04don333just curious why do keep using /me form stephyn?
09:06tomoj,(require 'clojure.contrib.seq-utils)
09:06clojurebotnil
09:06tomoj,(->> (clojure.contrib.seq-utils/indexed [:a :b :c :d :e]) (clojure.contrib.seq-utils/find-first (comp #{:d} second)) first)
09:06clojurebot3
09:06tomojthere must be a prettier way of doing that
09:07tomoj(first (find-first (comp #{:d} second) (indexed [:a :b :c :d :e])))
09:08cinim0dYou could also write index-of ^^
09:09tomojmy question is whether there is a prettier way of writing index-of
09:09stephynI was sort of surprised it didn't exist...I'm just learning and I've already re-written a number of functions :O
09:09stephynthanks for your help.
09:09tomojyou tend to use indexes far less often in clojure than in some other languages
09:10stephynwell, perhaps I need a different idiom to attack the problem. Are you familiar with the "Programming Challenges"?
09:10tomojI'm not
09:11tomojsometimes there is probably no better way than to use indexes, but it's just rarer in clojure, I think
09:11tomojbecause you can often get what you want just by mapping, reducing, filtering
09:12stephynwell, 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)
09:12chouserif 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.
09:13tomojstephyn: are you new to functional programming?
09:15tomojstephyn: do you happen to have a link to the problem?
09:15tomojif you're new to FP it can sometimes be difficult to think of a functional-style solution
09:16fliebelstephyn: I second that. I tend to start of with an atom for some sort of state I don't need in the end.
09:17tomojstephyn: for future reference, better to stay in the channel: get more feedback if it catches someone's eye
09:23tomojstephyn: yes, I don't think you need indexes for that problem
09:26jjidoyou will find it easier to create a new list with the desired data instead of updating the existing one in Clojure
09:45arkhI'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?
09:46mrBliss(some #(re-matches % s) [re1 re2...])
09:46arkhmrBliss: thank you
09:47tomojstephyn: seems you do probably need some indexes
09:48stephyntomoj: it still seems interesting to try something different. I'm thinking more of the SICP "build a language that solves the problem" approach.
10:00bhenrystephyn 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:01stephynbhenry: thanks.
10:34arkhsorry 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:34arkh,(split-with #(= '.' %) "172.16.102.0")
10:34clojurebot[() (\1 \7 \2 \. \1 \6 \. \1 \0 \2 \. \0)]
10:34arkh: (
10:36arkh,(split-with #(= \. %) "172.16.102.0")
10:36clojurebot[() (\1 \7 \2 \. \1 \6 \. \1 \0 \2 \. \0)]
10:37fliebel,(split-with +(= \. %) "..............172.16.102.0")
10:37clojurebotjava.lang.Exception: Unable to resolve symbol: =  in this context
10:37fliebel,(split-with +(= \. %) "..............172.16.102.0")
10:37clojurebotjava.lang.Exception: Unable to resolve symbol: % in this context
10:37fliebeldoh
10:37MayDanielUse clojure.string/split
10:37chouser,(.split #"\." "172.16.102.0")
10:37clojurebot#<String[] [Ljava.lang.String;@1d4cadc>
10:37chouser,(seq (.split #"\." "172.16.102.0"))
10:37clojurebot("172" "16" "102" "0")
10:38arkhthank you! I didn't even know about clojure.string
10:39arkhchouser: what you used is java String, right?
10:40chouserarkh: Java's regex Pattern has a .split method
10:40chouserthat's what I used
10:40arkhoh ... cool
10:41fliebelI keep forgetting to look at Java docs when looking for a function.
10:41arkhI totally should have known that : / #"\." is no String
10:44arkhand I think that exact line chouser wrote should be a clojure built-in, imho.
10:45jjido,(doc clojure.string/split)
10:45clojurebot"([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:46arkhfair enough
10:47jjido,(closure.string/split "172.16.4.12" \.)
10:47clojurebotjava.lang.ClassNotFoundException: closure.string
10:48Raynesjjido: You just typo'd a typo.
10:48jjidolol
10:49jjido,(clojure.string/split "172.16.4.21" \.)
10:49clojurebotjava.lang.ClassCastException: java.lang.Character cannot be cast to java.util.regex.Pattern
10:50jjido,(clojure.string/split "172.16.4.21" #"\.")
10:50clojurebot["172" "16" "4" "21"]
10:51jjidook
11:06rickmodeIf there some equivalent to defonce when using a let like the following? (let [count (atom 0)] (defn counter [] (swap! count inc)))
11:11fliebelHow helpful are the docs of Enlive… (doc template) => A template returns a seq of string.
11:11jjidoyou could use binding to move count in a separate thread maybe?
11:12fliebel(doc snippet) => A snippet is a function that returns a seq of nodes.
11:12clojurebotGabh mo leithscéal?
11:13stuarthallowayHello!
11:13fliebelstuarthalloway: Hey
11:14stuarthallowayAnybody here know the address for the studio backchannel?
11:14stuarthalloway...for those of us currently in clojure training...
11:14laurusHow do I log a REPL session to a file?
11:18laurusThere's no way to get a session transcript in Clojure?
11:27laurusIs (. System exit 0) the proper command to exit the Clojure REPL?
11:27Raynes(System/exit 0)
11:27laurusThanks Raynes :)
11:29jjidocontrol-d should work too or is that bad?
11:29laurusjjido, I just wanted an actual Clojure command to do it :p
11:30Raynesjjido: Nothing wrong with exiting a command-line REPL like that.
11:30iveyWhat's wrong with C-c C-k?
11:30Rayneslaurus: Incidentally, that's actually the Java way of doing it. It's just kind of pointless to wrap it in Clojure.
11:31laurusRaynes, yeah, I see. Actually I just did this: (defn exit [] (System/exit 0))
11:31laurus;)
11:31RaynesThat's fine. Wrapping it in Clojure itself would be a little pointless.
11:31laurusRight
11:33laurusBy 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:22kjeldahlI'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:30seangrove,(dotimes [x 5] 'a)
12:30clojurebotnil
12:30seangroveIs there a way I can collect the the return value from each of the dotimes?
12:30chouserkjeldahl: you just need to adjust your classpath
12:31chouserseangrove: no, dotimes is an imperative loop for side-effecty things
12:31chouser,(repeat 5 'a)
12:31clojurebot(a a a a a)
12:31drewrseangrove: use map or for
12:31chouser,(for [x (range 5)] 'a)
12:31clojurebot(a a a a a)
12:31seangrove,(doc repeat)
12:31clojurebot"([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."
12:32seangroveCool, thanks :)
12:32kjeldahlchouser: 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:33kjeldahlAny idea?
12:33kjeldahlThe exact error is: java.io.FileNotFoundException: Could not locate pw/planetwars__init.class or pw/planetwars.clj on classpath: (NO_SOURCE_FILE:0)
12:33kjeldahlI've confirmed that /home/marius/src/ai-contest-planetwars-clj/src/pw/planetwars.clj is there.
12:33tomojkjeldahl: how are you starting clojure?
12:34mrBlisskjeldahl: I've had similar problems, leiningen solved them for me
12:34kjeldahlWith the clj-env-dir script. But I've confirmed the the classpath inside the repl with " (println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))"
12:34tomojyes, you should really just use lein, there's a project.clj already conveniently there for you
12:35kjeldahlI'm not building, I just want it to read a source file...
12:35tomojand lein helps you do that by downloading the libs and starting repls or swank servers
12:35tomojs/lib/deps
12:36tomojotherwise, you'll just have to get the deps manually and set the classpath properly yourself
12:36tomojinspecting (System/getProperty "java.class.path") in your repl would be a good step towards doing that, if you wanted to for some reason
12:38kjeldahlProblem 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:39kjeldahlHm, 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:39chouserIt's got to be your classpath(s)
12:40kjeldahlIt 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:41chouserthat's one of them, yes.
12:41kjeldahlThat last dir, ending with src, contains pw/planetwars.clj .
12:46chouser(.getResource (clojure.lang.RT/baseLoader) "pw/planetwars.clj") returns nil?
12:46tomojthat doesn't make sense
12:48chouser(mapcat #(.getURLs %) (take-while identity (iterate #(.getParent %) (clojure.lang.RT/baseLoader))))
12:48chouserThat's something closer to the actual classpath being used by Clojure, I think.
12:49chousermine has 664 entires O_o
12:49kjeldahlchouser: Sense or not, that is what it does.
12:49kjeldahl(returns nil)
12:50chouserheh, I didn't say it didn't make sense. That's just par for the course with classpath.
12:50chouserok, returning nil makes sense. That simply means the classpath being used by clojure doesn't contain your .clj file
12:50chouserwhich we essentially already knew.
12:51kjeldahlIt also means clojure doesn't use java's classpath or?
12:51chouserthe question then is does the classpath being used by Clojure have the entries that we think it does.
12:51chouserkjeldahl: java has many classpaths
12:51chouseryay
12:52chouser(filter #(re-find #"/home/" %) (map #(.getPath %) (mapcat #(.getURLs %) (take-while identity (iterate #(.getParent %) (clojure.lang.RT/baseLoader))))))
12:52chousertry that.
12:52kjeldahlThe correct path is also in the first mapcat thingy suggested.
12:53kjeldahlfilter thingy: ("/home/marius/.clojure/jline-0.9.94.jar" "/home/marius/.clojure/" "/home/marius/src/ai-contest-planetwars-clj/src")
12:53chouserok, now *that* doesn't make sense. :-)
12:53kjeldahlchouse: Yeah, I guess my experimentation leaves a trace.. ;-)
12:55chouserhm, all my directory classpath entries end in /
12:55chousercould it be that?
12:57kjeldahlEven if I add the trailing slash where I set the classpath, it's still removed when I display it in clojure.
12:59chouserkjeldahl: huh.
13:01kjeldahlchouser: 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:03kjeldahlForget it. As suspected, operator error.
13:04kjeldahlMissed a hyphen in the long path.
13:09seangroveHow should I check if a variable is ... one of these {:a 5 :b 10}
13:10seangroveIs that really a PersistentArrayMap?
13:10grignaak,(map? {:a 10 :b 10})
13:10clojurebottrue
13:11grignaakseangrove: ^^
13:11seangroveAh, good stuff :)
13:11seangroveThanks
13:15boojumseangrove: but it will mutate into a PersistentHashMap when it grows
13:16boojumafair
13:24jweissis 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:29abrenkjweiss: Clojure 1.2 has annotation support, see "2.12 Java Annotations" in http://github.com/clojure/clojure/blob/1.2.x/changes.txt
13:31seangroveI can't see to destructure this correctly
13:31seangroveHow can I iterate over {:a 50 :b 100 :c 34} assigning each k:v to key value and doing something with them?
13:32tomoj,(for [[k v] {:a 50 :b 100 :c 34}] (str k v))
13:32clojurebot(":a50" ":b100" ":c34")
13:32lancepantzseangrove: you want to use for
13:32tomojlike that?
13:32lancepantzthere ya go
13:32seangroveHaha
13:33seangroveYes, that's it
13:33dakrone,(map (fn [[k v]] (println "key:" k "val:" v)) {:a 1 :b 2 :c 3}
13:33clojurebotEOF while reading
13:33seangroveI had some hacky thing involving (take 2)...
13:33dakrone,(map (fn [[k v]] (println "key:" k "val:" v)) {:a 1 :b 2 :c 3})
13:33clojurebot(nil nil nil)
13:33tomojif by "do something with them" you mean do side effects, that's a different story
13:33dakronealright, well that works, but doesn't show up
13:33seangroveNo, no side effects
13:33lancepantzseangrove: note you'll have to wrap that in (into {})
13:33tomojwell, just replace 'for' with 'doseq'
13:33tomojgood :)
13:33lancepantzthat's if you want a map back out
13:34seangroveNope
13:34seangroveConverting it all to strings in the end
13:34seangroveTrying to add in attributes for my html tags :)
13:46kotarakOeh? Does definterface require AOT compilation?
13:52dnolenkotarak: I didn't think so.
13:52dnolenpretty sure it's dynamic
13:53kotarakdnolen: ah. Ok.
14:24jfieldsis 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:24jfields(an unhandled exception that is)
14:25morphlingis there no function like assoc instead of assoc-in for update-in?
14:25morphlingupdate-in uses (assoc m k (apply f (get m k) args)) internally
14:27ohpauleezjfields: Like (System/exit)?
14:27ohpauleezhttp://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#exit%28int%29
14:28joshua-choiI've got a question. I want a sequential data structure that can split any of its elements into two, for text piece tables.
14:29joshua-choiEssentially replacing that element with something else and splicing another thing after too.
14:29joshua-choiAre finger trees what I want?
14:29chouserjoshua-choi: probably
14:29joshua-choiHow are you finger trees going? :)
14:30chouserpretty 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:30jfieldsohpauleez, 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:30joshua-choiIf there are any other Clojure data structures that might work, I'd love to know too...I want to make a text editor.
14:30chouserjfields: hm, some kind of global default error handler.
14:30ohpauleezyeah, that's what I would say too
14:31ohpauleezuse an error handler, or use error-kit on the entire system
14:31chouseractually, I'd look at the thread pool classes to see if that's parameterized there.
14:31clojureboterror-kit is http://pragprog.com/magazines/2009-07/when-things-go-wrong
14:32jfieldsyeah, Thread/setDefaultUncaughtExceptionHandler looks like what I need
14:33ohpauleezchouser: What's the likelihood of finger trees making their way into core? or a contrib for new data structures
14:35chouserohpauleez: almost certainly they'll get into contrib. core has a chance, of course that's up to rhickey.
14:35ohpauleezcool, I just started looking into them, they seem quite useful
14:36chouserohpauleez: yeah, very versatile
14:37chouserI wish I could get performance closer to sorted-maps, vectors, etc.
14:37chouserBut I'm concentrating on API now.
14:38joshua-choichouser: Would you say that the API is stable?
14:38chouserno
14:38chousersorry
14:48joshua-choichouser: No, it's fine. I'm just really happy that they're being implemented at all. Thanks for doing it!
14:51chousersure! I hope they end up being useful.
15:11joshua-choichouser: In your finger trees' finger-tree function, what is meter-obj? (finger-trees meter-obj x y z).
15:12chouserjoshua-choi: something that implements ObjMeter
15:13chouserSuch as len-meter
15:13jweissif 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:13dmiller2718rhickey: 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:13jweissi basically want an empty protocol, with annotated fn's -> methods
15:14chouserjweiss: gen-class
15:14joshua-choichouser: I see. That determines how the tree's nodes are labelled, right?
15:14jweisschouser- does gen-class support annotations now?
15:14chouserjweiss: I believe so.
15:14chouserjoshua-choi: yeah
15:14joshua-choiOkay, thanks.
15:14jweissok i'll try that
15:15chouserjoshua-choi: len-meter is for looking things up by index.
15:15chouseroh
15:15chouserbye.
15:15ohpauleezhaha'
15:27amalloyi'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:28raekamalloy: it might be due to remove being lazy
15:29raektry putting a (doall ...) around it
15:29raekif you want to measure the execution time
15:31amalloyraek: changed to (update-in hand [suit] #(doall (remove #{card} %))); is that what you mean? if so, it's still faster
15:31raek,(time (dotimes [_ 1e5] (disj (sorted-set 1 2 3 4 5 6 7 8 9 10) 5)))
15:31clojurebot"Elapsed time: 3080.067 msecs"
15:31raek,(time (dotimes [_ 1e5] (remove #{5} [1 2 3 4 5 6 7 8 9 10])))
15:31clojurebot"Elapsed time: 120.957 msecs"
15:32raek,(time (dotimes [_ 1e5] (doall (remove #{5} [1 2 3 4 5 6 7 8 9 10]))))
15:32clojurebot"Elapsed time: 797.188 msecs"
15:32chouseramalloy: how large is your set?
15:32amalloysmall
15:32raekremove does not compute anything until the sequence is realized
15:32chouseryeah, it's going to be mostly constants and overhead
15:33amalloyin 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:33jweissare there issues with using gen-class in the REPL? user> (gen-class), and then (user.) throws ClassNotFound
15:33raekjweiss: yes, gen-class can only be used with ahead-of-time compilation
15:34raekhrm, could one use (compile my.name.space) to do aot at the repl?
15:35jweissraek: i just tried that
15:35jweissCould not locate user__init.class or user.clj on classpath:
15:35jweissi guess AOT is for clj files on disk only?
15:36clojurebotAOT genclass is http://paste.lisp.org/display/70665 and http://clojure-log.n01se.net/date/2008-11-18.html#14:19
15:36raekmaybe the namespace name has to be quoted
15:36jweissraek: i ran (compile 'user)
15:36raekdo you have a user.clj file?
15:36jweissraek: no - i'm at the REPL
15:37raekit doesn't compile an already loaded file
15:37raekonly source files, I think
15:37chouseryeah
15:37jweissok, well, that'll work for my ultimate purpose, just makes it harder to play with :)
15:38raekgen-class is mainly for java interop where you need to compile java code that uses clojure code
15:38ohpauleezjweiss: lein interactive my make it easier
15:38jweissraek: yeah, that is what i am doing - want to write testng tests in clojure
15:38raekproxy can be used for the java-in-clojure situation
15:38jweisstestng is a java lib that reads classes for @Test annotations on public methods, and runs them
15:39jweissraek: i don't think proxy supports annotations
15:39jweissi am not sure that gen-class does either :) but i'll try it
15:39raekthere is some support for annotations in at least one of the interop constructs
15:39raeksince 1.1
15:40raekhttps://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117
15:42tomojwhoa
15:42tomojI never thought it would happen
15:43raekhrm, I'm uncertain about whether it was 1.1... it is there in 1.2 at least
15:45LauJensenhttps://secure.trifork.com/aarhus-2010/freeevent/register.jsp?eventOID=2698
15:46LauJensenTry loading that, then once its done, I'll keep a connection with conviva.com, I cant break it
15:46LauJensenSorry, wrong chan :)
16:09LauJensenSorry, wrong chan :)
16:10jneirahi people!
16:15arkhHow would one make this work:
16:15arkh,(every? #(0 <= % <= 255) [20 21 22])
16:15clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
16:15joshua-choiYou want #(<= 0 % 255) I imagine
16:15arkhoh wow
16:16arkh*sheepish* thank you
16:16joshua-choiNo problem
16:17jneira,(let [t Object v 2] (with-meta {:value v} {:type t}))
16:17clojurebotEval-in-box threw an exception:java.lang.StackOverflowError
16:17jneirajum
16:18jneirastrange error
16:18jneirastrange in my ignorance of course
16:20chouserseems strange to me
16:20chouser,(with-meta {} {:type Object})
16:20clojurebotEval-in-box threw an exception:java.lang.StackOverflowError
16:20jneira:type is only available on multimethods
16:20jneira?
16:20chouserno
16:21jneira,*clojure-version*
16:21clojurebot{:interim true, :major 1, :minor 2, :incremental 0, :qualifier "master"}
16:21jneirajum
16:21chouserit's the printing of it that's blowing up.
16:22Raynes,(clojure-version)
16:22clojurebot"1.2.0-master-SNAPSHOT"
16:22jneirayep in the sea of traces i saw something about print
16:22chouser,(:value (with-meta {:value 2} {:type Object}))
16:22clojurebot2
16:22chousercreating and using it is fine.
16:22wwmorgan,(meta (with-meta {} {:type Object}))
16:22clojurebot{:type java.lang.Object}
16:22jneiraok
16:23jneiraa bug then?
16:23chousermust be
16:29chouserweird
16:29chouser,(print-method (with-meta {} {:type Object}) *out*)
16:29clojurebotjava.lang.StackOverflowError
16:29chouser,(#'clojure.core/print-meta (with-meta {} {:type Object}) *out*)
16:29clojurebotnil
16:30chouser,(#'clojure.core/print-map (with-meta {} {:type Object}) #'clojure.core/pr-on *out*)
16:30clojurebot{}
16:30chouserthe two things that print-method call work fine. but print-method overflows.
16:30chousergotta run.
16:36arkh,(int "10")
16:36clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
16:36arkh: /
16:36Raynes-> (Integer/parseInt "10")
16:36sexpbot=> 10
16:36Raynes-> (read-string "10")
16:36sexpbot=> 10
16:37jneirainteresting trace exploring
16:38jneira,(doc print-method)
16:38clojurebot"; "
16:38arkhthanks Raynes
16:41jneirathank chouser, do not know if i should open a ticket ...
16:41arkhhm - I still get a ClassCastException when trying to Number work on a String after read-string. Clojure should have its own (Integer/parseInt)
16:41arkh*to do
16:42Raynes(doc read-string)
16:42clojurebot"([s]); Reads one object from the string s"
16:42Raynesread-string doesn't just read integers, but reads any object.
16:42arkh,(class (read-string "10"))
16:42clojurebotjava.lang.Integer
16:43arkh: / ... k, nvm
16:43RaynesIf your numbers are user input, you should use Integer/parseInt to avoid security issues.
16:43arkhgood to know! They are user input
16:44jneira,(do (defprotocol Monad (>>= [m f])) (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))
16:44clojurebotDENIED
16:44RaynesCan't def stuff.
16:44jneiraeyyy
16:44jneirajeje no haskell stuff :-P
16:46jneiraimplement the constructor function return is more tricky
16:47ChousukeI wrote a toy monad implementation based on protocols once
16:47ChousukeIt's in a gist somewhere
16:47jneira(let [proto (defprotocol Monad (>>= [m f]))] (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))n
16:48jneira,(let [proto (defprotocol Monad (>>= [m f]))] (extend clojure.lang.PersistentList Monad {:>>= (fn [xs f] (mapcat f xs))}) (>>= '(0) (comp list inc)))
16:48clojurebotDENIED
16:48jneirajum
16:48RaynesSeriously, you can't def stuff. :P
16:48Chousukehttp://gist.github.com/312281 here.
16:48jneirainteresting Chousuke
16:49jneirai am going to take a look
16:49ChousukeI still don't know how I managed to write the lift function
16:51jneirai have not reach this point ... i am trying to implement return with multimethods :-/
16:52jneirafor learning, i really like macro acrobatics of clojure.contrib.monads, but too advamced for me :-P
16:56jneiradispatch on return type of functions is neat :-/
17:35jjidois the (last) function really slow on vectors?
17:37wwmorgan,(time (last (vec (range 1000000))))
17:37clojurebot999999
17:37clojurebot"Elapsed time: 1816.7 msecs"
17:37jjidoI don't understand why a version that does (vec (cons)) is faster than one that doesn't
17:37jjidolooks slow
17:38wwmorganjjido: 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:39jjido,(time (nth (vec (range 1000000)) 999999))
17:39clojurebot999999
17:39clojurebot"Elapsed time: 1044.719 msecs"
17:39jjido,(time (nth (vec (range 1000000)) 999999))
17:39clojurebot999999
17:39clojurebot"Elapsed time: 1418.003 msecs"
17:39jjidommh?
17:40wwmorgan,(time (do (vec (range 1000000)) 0))
17:40clojurebot0
17:40clojurebot"Elapsed time: 996.783 msecs"
17:40jjidook
17:42wwmorgan,(let [v (vec (range 1000000))] (time (last v)) (time (nth v (dec (count v)))))
17:42clojurebot999999
17:42clojurebot"Elapsed time: 226.482 msecs" "Elapsed time: 0.05 msecs"
17:44jjidowow my algo is 5x faster now
17:45wwmorganawesome :-)
17:47jjidoI want to share it: http://pastebin.ca/1940906
17:47jjidoUse as (merge-sort-cont unsorted-vector println)
17:51arkh,(if (and (map #(= 1 %) [3 2 1])) true false)
17:51clojurebottrue
17:51arkh?
17:54ninjudd,(if (some #(= 1 %) [3 2 1]) true false)
17:54clojurebottrue
17:54ninjudd(if (every? #(= 1 %) [3 2 1]) true false)
17:55ninjudd,(if (every? #(= 1 %) [3 2 1]) true false)
17:55clojurebotfalse
17:55arkhI can use every, though it seems like 'and' should work, too : /
17:56arkh'every?' looks better : )
17:56jneira,,
17:56clojurebotEOF while reading
17:59joshua-choichouser: In your finger trees, what is the string-meter for?
17:59chouserdebugging
18:00chouserit'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:02amalloyarkh: a seq always evaluates to true no matter what's in it
18:02amalloyif you really prefer and to every (IMO yuck), try (apply and (map ...))
18:03arkhamalloy: cool - thank you for explaining it to me. Without knowing that it seemed really odd.
18:06amalloywelcome. look forward to being surprised by that every so often in the future
18:07amalloy,(if (filter zero? (range 10 20)) true false)
18:07clojurebottrue
18:12amalloyhow do i specify infinity? i see that Double/POSITIVE_INFINITY displays as Infinity, but entering Infinity at a prompt throws an exception
18:14arkhamalloy: 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:15raek,(if (seq (filter zero? (range 10 20))) :truthy :non-truthy)
18:15clojurebot:non-truthy
18:16amalloyarkh: 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:16arkhnow I'm confused again : )
18:17amalloyarkh: (seq x) returns a sequence if x has elements, else nil
18:17amalloyraek is just trying to confuse us
18:17arkh,(if (and (seq (filter zero? (range 10 20)))) :truthy :non-truthy)
18:17clojurebot:non-truthy
18:17amalloy:)
18:18amalloy,[(filter zero? (range 10 20)) (seq (filter zero? (range 10 20)))]
18:18clojurebot[() nil]
18:18arkhevil!
18:19amalloyaw, i just realized i missed my chance to use juxt:
18:19amalloy,((juxt identity seq) (filter zero? (range 10 20)))
18:19clojurebot[() nil]
18:19raekseq is also used to force a lazy sequence to yield either nil or a cons (or any ISeq)
18:19arkhthat seems like an unwanted inconsistency - but then I'm still learning
18:20raekif 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:21amalloyarkh: 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:21arkhraek: that sounds like something Confucius would say
18:22raeka really really really lazy sequence: http://gist.github.com/480608
18:22raekit's so lazy that it outsources the element generation to the user... :-)
18:23amalloyhah
18:23raek(ask-the-user-seq) returns a LazySeq object
18:23raekwhen seq is called on it, a message box will show up and ask the user for a value
18:23amalloyreally lazy sequences are more like (defn be-lazy [args] nil (comment TODO))
18:23clojurebotWhy are you asking *him*
18:24raekif the user chooses cancel, (seq (ask-the-user-seq)) returns nil
18:25raekso a LazySeq is like something that hasn't decided whether it's gonna be a cons or nil
18:25raektherefore, nil-punning requires calling seq on it
18:26arkhnil-punning?
18:26amalloysee, you're filling his head with CL ideas, raek
18:27arkhlaziness is like slow kung-fu or something - still learning it
18:27raek(if value ... ...) ; <-- nil-punning on 'value'
18:27arkhk
18:27raekto check whether it is something or not
18:27amalloynil-punning is basically treating an empty seq as nil, which can be more convenient when you're recursively creating a sequence
18:28raekjust remember that in Clojure, () is not nil, and () is also truthy
18:29amalloy(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:30amalloythe (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:30arkhamalloy: I was just about to ask 'why', but that makes sense
18:30raek(loop [a (seq ...)] (prn a) (when a (recur (next a)))) would be the clojure way, (next x) = (seq (rest x))
18:31amalloyyes yes, but we're showing him how seqs work
18:31raekwhere ... is any (potentially empty) collection
18:32raeksorry for skipping ahead...
18:32arkhso the recur to the top of the loop uses (seq) ?
18:32arkhwhen there are no more items in (next) ... is (seq) being called each recur?
18:33raekin my example, yes
18:33grignaakI 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:33raek,((juxt next rest) [1])
18:33clojurebot[nil ()]
18:34raekso the when will only get values that has passed throught seq
18:35arkhI didn't know values passed from recur to the top somehow had any original functions/verbs applied to them
18:36amalloygrignaak: what about something like this? (defn make-dostuff-fn [param1 param2] (fn [x] (do-stuff-with param1 (and param2))))
18:36raekarkh: there is no magic going on... seq is called because next calls it internally
18:37raek(defn next [x] (seq (rest x)))
18:37arkhok good - so no top-of-the-loop implied stuff
18:38arkhdoh - I didn't catch the next vs. rest difference in the two examples
18:42grignaakamolloy: 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:45amalloyyeah, if there are five things you might want to tune, it's hard to avoid having five parameters to something
18:52grignaakthis is what it looks like now: http://pastie.org/1159426
18:53dsantiagoarohner, are you around?
18:54amalloygrignaak: i don't feel up to diving through the whole thing, but you can replace (fn [& args] x) with (constantly x)
18:55arohnerdsantiago: yeah, what's up?
18:55grignaakI guess I could also remove the peek and pop params if there is an implementation of a queue wrt peek/pop/conj
18:55dsantiagoAhrohner, hi, I was just enjoying using Scriptjure, and I was wondering if there was some way to do something like (. (getElement "myId") value).
18:56dsantiagoRight now, that results in getElement('myId').value()
18:56grignaak(lists and vectors both act like stacks wrt peek/pop/conj)
18:56arohnerdsantiago: that's what I would expect it to do
18:56arohnerwhat do you want it to do?
18:57dsantiagoAccess the member called value.
18:57arohneruse aget
18:58dsantiagoAh, OK, I thought that was for arrays only.
18:58arohnerclojure'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:58amalloygrignaak: check out http://tinyurl.com/22ps9cw - i don't know if it's any good, but it sounds like what you want
18:58arohnerfoo.bar and foo["bar"] are equivalent in JS
18:58dsantiagoOh no, I understand completely. My questions was more "Is there some way to access a member."
18:58dsantiagoI see. Thank you.
19:00grignaakamalloy: yep, I'm using that for djikstra's/a*, and lists for dfs, I guess I could wrap it for dfs
19:01grignaak*bfs (the second dfs)
19:14mabeswhat 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:46trengofhi, 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:46amalloy,(apply and [true false])
19:46clojurebotjava.lang.Exception: Can't take value of a macro: #'clojure.core/and
19:46amalloyboo
19:46chousertrengof: take a look at 'every?'
19:47trengofamalloy: since map returns a list that doesn't work
19:48trengofdoesn't work with vectors either hmm
19:48amalloyno, it doesn't work because and is a macro :P. apply turns the list into real args
19:49amalloychouser is right that every? is the right answer, but you could do it with an anonymous function too
19:49trengofyeah thanks, i'm looking at every? now
19:50chousertrengof: you might also want 'identity'
19:51amalloy,(every? identity [2 false])
19:51clojurebotfalse
19:51amalloy,(every? identity [2 true])
19:51clojurebottrue
19:52chouserthat's not quite like 'and', which returns the the first falsey value.
19:52trengofmuch simpler: (reduce and (map a-boolean-test? a-vector))) -> (every? a-boolen-test? a-vector)
19:52chouserbut one hardly ever cares.
19:53amalloyyeah, it's rare to care whether your test failed because of a false or a null
19:54chouser,(first (remove identity [1 nil]))
19:54clojurebotnil
19:54chouser^^^ just in case. ;-)
19:54amalloychouser, that's sick
19:58amalloychouser: 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:59chouseramalloy: sorry for not responding. I'm not sure if we've missed the window for changes in this edition or not.
20:04amalloynp. if it goes to print this way i'll show off to everyone how much smarter than the authors i am :)
20:04chouser:-)
20:05joshua-choichouser: Finger tree question. What's the intended function of string-meter?
20:05chousertesting and debugging
20:05chouserjoshua-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:06joshua-choiOkay, thanks
20:07joshua-choi,(hash {})
20:07clojurebot0
20:07joshua-choi,(hash [])
20:07clojurebot1
20:07joshua-choi,(hash {:a 3, :b 2})
20:07clojurebot2027821080
20:08joshua-choichouser: 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:08chouserhm, going to sort your finger tree by hash?
20:08chouseroh, not sort by hash?
20:09joshua-choiA finger tree that sorts by insertion position but also can look up nodes by hash...
20:10joshua-choiEh, I don't know. But I need to be able to refer to nodes.
20:10joshua-choiI want to create a text piece table in Clojure: http://www.cs.unm.edu/~crowley/papers/sds.pdf
20:11chouserjoshua-choi: gotta go, but I will ponder your question.
20:11joshua-choiYeah, please.
20:11joshua-choiThansk
20:11chouserI can't say I'm hopeful, but mayber there's some clever trick...
20:11joshua-choiTake a look at that paper.
20:11joshua-choiIt's very easy.
20:11joshua-choiPay attention to the piece table section.
20:11joshua-choiCiao
21:39seangrove,(doc clojure.contrib.string/take)
21:39clojurebot"([n s]); Take first n characters from s, up to the length of s."
21:40seangrove,(clojure.contrib.string/take 5 "this is a test")
21:40clojurebot"this "
21:42seangrove,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (take length (second (clojure.contrib.string.split #":" item))))
21:42clojurebotjava.lang.ClassNotFoundException: clojure.contrib.string.split
21:42seangrove,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (take length (second (clojure.contrib.string/split #":" item))))
21:42clojurebot(\s \p \a \m)
21:42seangroveHrm
21:42seangroveah
21:42seangroveNot string/take
21:42seangrove,(let [item "4:spam" length (Integer. (first (clojure.contrib.string/split #":" item)))] (clojure.contrib.string/take length (second (clojure.contrib.string/split #":" item))))
21:42clojurebot"spam"
21:42seangroveYup
21:50seangrove,["a" 50 "b" 60"]
21:50clojurebotEOF while reading string
21:50seangrove,["a" 50 "b" 60]
21:50clojurebot["a" 50 "b" 60]
21:50seangroveQuite right clojurebot
21:51seangrove,(for [key ["a" 50 "b" 60]] (print key))
21:51clojurebot(nil nil nil nil)
21:51seangrove,(for [[key val] ["a" 50 "b" 60]] (print (str key ":" val)))
21:51clojurebotjava.lang.UnsupportedOperationException: nth not supported on this type: Integer
21:51seangroveNope
21:52seangroveDon't think I have this destructuring thing down :P
21:52seangroveI'm actually trying to turn ["a" 50 "b" 60] into {:a 50 :b 60}
21:54seangroveThink I might have it...
21:54seangrove,(apply hash-map ["a" 50 "b" 60])
21:54clojurebot{"a" 50, "b" 60}
21:55seangroveClose... but not sure how to call (keyword) on "a" and "b" there
21:55lancepantzthere is a keywordize keys fn in contrib
21:56lancepantzor for
21:56seangrove,(clojure.walk/keywordize-keys (apply hash-map ["a" 50 "b" 60]))
21:56clojurebotjava.lang.ClassNotFoundException: clojure.walk
21:57seangrovefor would probably work.. just feels like I'm missing something elegant here
21:58lancepantz,(into {} (for [[k v] (partition 2 ["a" 50 "b" 60])] [(keyword k) v]))
21:58clojurebot{:a 50, :b 60}
21:59lancepantzthat's probably not the most elegant however
22:00seangrovethis says that keywordize-keys was added in clojure 1.1? http://richhickey.github.com/clojure/clojure.walk-api.html
22:01lancepantzyeah, what you had earlier should work on a repl
22:01lancepantzi'm not how to use fn's outside of core with clojurebot
22:03seangrovethanks :)
22:21seangrove,(println (clojure.contrib.string/join "" (butlast (string/partition #"e" "li1ei40e4:seane")))))
22:21clojurebotjava.lang.Exception: No such namespace: string
22:21seangrove,(println (clojure.contrib.string/join "" (butlast (clojure.contrib.string/partition #"e" "li1ei40e4:seane")))))
22:21clojurebotli1ei40e4:sean
22:21seangroveAny more elegant way to do that?
22:24lancepantz,(.substring "li1ei40e4:seane" 0 -1)
22:24clojurebotjava.lang.StringIndexOutOfBoundsException: String index out of range: -1
22:24lancepantzblah, damn java
22:26lancepantz,(let [s "li1ei40e4:seane"] (.substring s 0 (dec (.length s))))
22:26clojurebot"li1ei40e4:sean"
22:27seangroveHmm, I think that might work..
22:27seangroveCertainly more legible than what I have :P
22:27lancepantzi usually end up using String directly instead of contrib.string
22:28lancepantz,(let [s "li1ei40e4:seane"] (.substring s 0 (dec (count s))))
22:28clojurebot"li1ei40e4:sean"
23:28cinim0dclojurebot: doc def. needs example for all those useful core functions.
23:28clojurebotthe doctor is out
23:29cinim0dmm
23:29cinim0ds/clojurebot:/clojure