#clojure logs

2009-03-07

00:37cmvkkwell if we're going to use weird characters, I think we should use the snowman.
00:37abrooksI say that as a member of the querty/English crowd...
00:37abrookscmvkk: Oh, of course.. how could I have overlooked that. http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/;-)
00:38abrooksOoops...
00:38abrookscmvkk: Oh, of course.. how could I have overlooked that. /;-)
00:38cmvkkheh, i was hoping there was somehow a snowman i missed in that monad tutorial.
00:38abrooksI just need to figure out the compose key for "snowman"
00:39abrooksThe X11 compose/multi-key is a great mechanism for accessing non-primary symbols.
00:40abrooks(...map... foo bar)
00:40abrooksActually, I liked the =map= and =filter= myself.
00:42abrooksLook, if non-ascii was good enough for APL it's good enough for Clojure. ;-D
00:43cmvkki think we should utilize the wide range of unicode available, and make it so that every core function is only one character long.
00:44cmvkkyou could accomplish that with chinese characters alone!
00:52abrookscmvkk: In my own code I've found it nice to use unicode symbols in Clojure (mostly Project Euler) but I think it's the right decision to keep the core language free of unicode.
00:53abrookscmvkk: I know you were having fun. :)
00:54cmvkkof course...but i do welcome a day when unicode input is so easy that keeping non-ascii characters out of a language isn't necessary anymore
00:57durka42is c.c.monads broken?
01:02durka42m-lift doesn't seem to work because m-bind is nowhere to be found
01:02durka42,(use 'clojure.contrib.monads)
01:02clojurebotjava.io.FileNotFoundException: Could not locate clojure/contrib/monads__init.class or clojure/contrib/monads.clj on classpath:
01:12durka42never mind
01:35Raynes-durka42: You are broken :>
01:45replacaQ: so, I'm updated to the lazy stuff and lazy-cons seems to be gone, but cons isn't really lazy
01:45replacawhat's the right stategy?
01:46replaca*strategy
01:49cmvkklazy-seq?
01:49replacaahh, ok.
01:50replacais there a doc that outlines the effect of the changes (or a google message)?
01:50replacaI wasn't paying very close attention when all that happened
01:50cmvkkhttp://clojure.org/lazy is i think the correct one
01:51replacaRTFM, Tom :-)
01:51replacathanks, cmvkk!
01:51cmvkkactually, i'm not sure how you even access that page from anywhere.
01:52brennanchttp://paste.lisp.org/display/76606
01:52replacayoou mean, besides getting someone to post a link in IRC? :-)
01:52cmvkkthat's where I got it from...
01:53brennanccan someone explain this? It's from the Programming Clojure book. I don't understand what is getting passed to map and how it is even valid.
01:53brennancpt is something like [5 10]
01:53replacawe're all part of a secret society!
01:53cmvkkthe list being passed in is [(pt 0) (pt 1) 1 1] it seems
01:53brennanc([5 10] 0) is not a valid expression though
01:53cmvkkand the fn is #(* point-size %) which is just (fn [x] (* point-size x))
01:53cmvkkhmm
01:54brennanc(* point-size [5 10] 0) makes no sense to me
01:54cmvkkwait, what does (pt 0) return?
01:54brennancpt is not a function operand so I don't get how it is even valid
01:55brennancpt is passed as [5 10] in the example
01:55cmvkkohhh!
01:55replacabrennanc: ,([5 10] 0)
01:55replaca,([5 10] 0)
01:55clojurebot5
01:55cmvkkyeah, vectors are functions of their indexes.
01:56replacaI didn't know that, but guessed from context
01:56brennancahhh
01:56replacapretty cool
01:56brennancI never would have guessed that one, but it makes perfect sense now
01:56replacabrennanc: this is where the REPL helps: if it doesn't seem right just type it in and see what happens :-)
02:11Raynes-When a function is screwing up, I always break it down and evaluate every piece in the REPL. <3 REPLs.
02:12brennancyeah, I got the result and knew it worked, just didn't understand how it was valid :)
02:13brennancor what the logic was behind it
02:13brennanccmvkk's explanation cleared it up instantly
02:16Raynesbrennanc: In case you didn't know it, maps are the same way.
02:17brennancyup, thanks
02:17Raynes,({:akey "This is a value." :anotherkey "This is another value."} :akey)
02:17clojurebot"This is a value."
02:17RaynesThat's always fun.
02:17brennancanything else it works with?
02:18RaynesI don't think so.
02:18brennanck
02:20hiredman,(:key {:key 1 :a 2})
02:20clojurebot1
02:20brennancok, got a bunch of questions about this one
02:20brennanc(defn move [{:keys [body dir] :as snake} & grow]
02:20hiredman,('a {'a 1 'b 2})
02:20clojurebot1
02:20hiredmanthat is hash destructuring
02:21hiredmanwhich you kind find out about on the special forms page on the website under let
02:21brennancwhere would I find docs for that?
02:21hiredmanclojurebot: destructuring?
02:21clojurebotdestructuring is http://clojure.org/special_forms#let
02:21brennancthanks, will read
02:22hiredmanthat fuction takes a hash {:body _ :dir _}
02:23hiredmanbody is bound to (:body hash) and dir likewise, those whole hash is bound to snake
02:23hiredmanthen it takes a variable number of other arguments that are availble in a sequence bound to grow
02:25brennancthe & var-name is another way of saying it is optional, right?
02:27hiredmanthat and it binds to a sequence
02:28hiredman,((fn [ & x ] x) 1 2 3 4)
02:28clojurebot(1 2 3 4)
02:28brennanc,((fn [& x] x) )
02:28clojurebotnil
02:29brennanc,((fn [& x] x) (list))
02:29clojurebot(())
02:33replacaI was using nil? alot in loops to check for the empty list! :-(
02:34brennanc,(identical nil ())
02:34clojurebotjava.lang.Exception: Unable to resolve symbol: identical in this context
02:34brennanc,(identical? nil ())
02:34clojurebotfalse
02:35replacayeah, nil? foo used to work when you ran off the end of a list, but not anymore!
02:35replacaand the result tends to be an infinite loop/recur
02:35hiredmanwell, it still does if you (seq ...) the list
02:35hiredman,(doc next)
02:36clojurebot"([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil."
02:36replacaor you can just use empty?
02:36hiredman:(
02:36replacanot good?
02:37hiredmanasthetically unpleasing
02:38replacahmm, to check the end of the list? I don't get it
02:38brennancthe sequence video talks about it towards the end
02:38brennancISeq interfaces will return nil if you try to get another element an there is nothing there
02:39hiredmanerm
02:39brennanc...hopefully I remembered that correctly or am saying it right
02:39hiredmanthings have changed
02:39brennanclol
02:39replacathat went out with laziness
02:39brennancyet another inconsistency
02:39replacathat's what was breaking in my code
02:39hiredmanit used to be impossible to have empty sequences, if you tried you just got nil
02:40hiredmannow it is possible
02:40brennanc,(rest [])
02:40clojurebot()
02:40brennancit used to return nil
02:40cmvkkergh.
02:41replacahiredman: are you suggesting that I should use next instead of rest?
02:41cmvkkso i have these two functions i have to call hundreds of thousands of times in a row, and they both are exactly the same but for a caching system.
02:41hiredmanthat is one way t ogo
02:41hiredmanif you don't need full laziness
02:41cmvkkone uses a ref with a vector and assoc to create a ring buffer. the other stores only the immediately previous value and its number as an atom, in a vector of size 2.
02:42replacahiredman: but empty? is bad? that still confuses me
02:42hiredmannot bad
02:42cmvkkso the first one updates two refs and uses assoc, and the second one updates one atom and replaces the vector inside entirely.
02:42cmvkkbut the ref one is FIVE TIMES FASTER than the atom one.
02:42cmvkkatoms are supposed to have less overhead than refs!
02:42hiredmanfor low contention
02:42hiredman(I believe)
02:43hiredmanif you program does nothing but hit the atom a ref will perform better
02:44cmvkkwell it grabs the previous value, does some unchecked math against it and different value, then stores the resultant value where the previous value used to be.
02:44hiredmanactually, I should say, I don't know that for a fact
02:44brennancwhat's the point of atoms? why can't you just call def again if you want to set it to something else?
02:44hiredmanick
02:44hiredmanbrennanc: def once
02:44hiredmanand never again
02:44cmvkkbecause it might be concurrent later.
02:45brennanccmvkk: what do you mean by that?
02:45hiredmanyou should only ever re-def stuff in the repl
02:45cmvkkre-deffing is not thread safe....is it? i don't think it is?
02:45hiredmanand def only operates in the global space
02:45Chouseratoms make sure you're transitioning in a consistent way
02:46Chouserno read-calc-write race condition errors with atom and 'swap!'
02:46cmvkkin any case, i tried making a version that used two refs and did the same things as the atoms, and it was slower than the atom version.
02:46cmvkkso i have no idea what it is about the ring buffer version that's so much faster.
02:46hiredman,(let [a (atom 0)] (swap! a inc) @a)
02:46clojurebot1
02:47cmvkkit's actually only a small part of the program, but it slows the thing down from 22 seconds to 97 seconds.
02:48Chouserre-deffing is atomic -- you're not going to end up in some broken state. but (def foo (inc foo)) has a race
02:50brennancso an atom will wait until other transactions are done before it will set its value?
02:51hiredmanfunctional programming is a thing of elegence and beauty, re-defing is like using a non-synthetic motor oil
02:51hiredmanatoms set their value atomically
02:51hiredmancompare and swap
02:53Chouseratoms don't cooperate with transactions. 'swap!' has a side-effect.
02:54cmvkkit would be nice if atoms could synchronize somehow
02:54Chouserthen they'd be a ref. :-)
02:54hiredmanword
02:55cmvkkwell i'm changing the value of two different numbers, and i want to do it atomically. Should I just use two refs instead of an atom with a size-2 vector?
02:55cmvkkwhich would be faster?
02:55hiredmansounds like time for a profiler
02:56cmvkkwell i'm using a 'time' thing. but like i said: refs with a ring buffer = 22 seconds, one atom with a size-2 vector = 97 seconds.
02:56cmvkksomething seems awfully off about that.
02:56Chouseryou've got *warn-on-reflection* on?
02:57cmvkknope, let's try that.
02:58cmvkkhaha, thanks Chouser.
02:59Chouserreflection hurts, eh?
02:59cmvkkthe difference between the two fns: on the atom one, i wasn't wrapping the result of the atom deref in (int ...)
02:59cmvkkso unchecked-add and unchecked-divide couldn't resolve.
03:01cmvkkthis renderer is still quite a bit slower than real time, which is disappointing, but at least it's getting there...
03:01cmvkkI can do 8 seconds of music in 20 seconds now.
03:03Chouserreflection is most punishing, but boxing and unboxing are a next.
03:03ChouserYou're sure you're not doing either more than necessary?
03:03Chouserthat's a somewhat tougher question to answer in my experience.
03:03cmvkkI have no idea. well reflection is okay. the only things left that warn about that are the parts that actually write data out to file.
03:03cmvkkand i know that's not the bottleneck.
03:04Chouserok, that's good.
03:04cmvkkthe way the system is designed makes it hard, i think, to make sure things are going through correctly.
03:04cmvkkit uses lots of functions that take closure arguments and return new closures that call the argument closures, etc
03:05cmvkkints are 'supposed' to be returned a lot, but who knows.
03:05Chouserevery clojure functions takes and returns only boxed numbers, never primitives.
03:05cmvkkfns never return primitives?
03:05Chouserright
03:05Chouseralways Objects
03:06cmvkkso what DOES return primitives? just (int ...) and all those unchecked-math functions?
03:06Chouserin a few limited circumstances you can use a macro or better definline to factor out common code without losing primites.
03:07Chouseronly locals and java interop can use primitives.
03:07cmvkk:( do you think this has a chance of changing ever?
03:07Chouseras soon as the JVM gets tagged numbers, which apparently won't be very soon at all.
03:08brennanchow popular is clojure? any companies using it yet?
03:08cmvkkif you call (int ...) on something that's already an int, that's not a performance hit is it?
03:09hiredmanrich has mentioned a special function interface for return various primitives numbers
03:09Chouserbrennanc: some companies are using it, yes.
03:09ChouserI was asked about it in job interview the other day.
03:10brennancthat's cool. my boss is a developer and thinks PHP is the best language ever. lol
03:10ChouserI really shouldn't be up. good night, all.
03:11albinoheh, go php
03:11brennancI'm getting sick of writing (for $i=0; $i<$something; $++)
03:11hiredman:(
03:12hiredmanI started looking at some kind of "write something like clojure, compile to php" scheme
03:12brennancor having to store expressions into temp variables that only get used once because it won't let put an expression in certain forms
03:13brennanchiredman: so it takes a list and outputs php code?
03:14hiredmanmore or less
03:14Chouserbrennanc: http://groups.google.com/group/clojure/msg/1d215a79a697a68a
03:14hiredmanI have been ignoring php for a while, but when I have to deal with it again, I may start it again
03:15hiredmanmy current idea is clojure->json->interpreter written in php that "executes" json
03:16hiredmanthat way I would not have to write a parser
03:16brennancI wrote some small code that is a forth like interpreter and ported it to PHP, javascript, and actionscript
03:16brennancnot a whole lot of api in it but got the parsing done and everything
03:17hiredmanthen you should write the clojure->php bridge
03:17hiredman:)
03:17brennancI'd be tempted with what I have to deal with at work. :)
03:18brennanconly been learning clojure for about a week now. have to give it at least another week. ;)
03:19hiredmanbut it would help you learn, ask Chouser.
03:21replacagoodnight all! Happy late-night clojuring
05:57Lau_of_DKHey guys
05:58hoeckhey lau
05:58kotarakOl�, Se�or Lau.
05:59Lau_of_DKAssume I have a datastructure like ({:alpha 1 :beta 2 :gamma 3} {:alpha 4 :beta 5 :gamma 6}) and I want to export that to CSV: 1,2,3,4,5,6 in that order - is there an elegant way to accomplish that?
05:59Lau_of_DKOla mon Kota
05:59Lau_of_DKUnd mein The Hoeck :)
06:00hiredmanmapcat vals
06:00kotarak,(apply str (interpose "," (map val (concat {:alpha 1 :beta 2 :gamma 3} {:alpha 4 :beta 5 :gamma 6}))))
06:00clojurebot"1,2,3,4,5,6"
06:02Lau_of_DK,(apply str (interpose "," (map val (concat {:zeta 1 :beta 2 :gamma
06:02Lau_of_DK 3} {:zeta 4 :beta 5 :gamma 6}))))
06:02clojurebotEOF while reading
06:02Lau_of_DK,(apply str (interpose "," (map val (concat {:zeta 1 :beta 2 :gamma
06:02Lau_of_DK 3} {:zeta 4 :beta 5 :gamma 6}))))
06:02clojurebotEOF while reading
06:02Lau_of_DKHmm, why the bork ?
06:03Lau_of_DKWhat Im trying to say is, that it works by the assumption that your keys are alphabetically stored, mine aren't
06:03hiredman(comp sort mapcat)
06:03kotarak,(apply str (interpose "," (mapcat vals (list {:alpha 1 :beta 2 :gamma 3} {:alpha 4 :beta 5 :gamma 6}))))
06:03clojurebot"1,2,3,4,5,6"
06:04kotaraksorted-map?
06:04Lau_of_DKFunny, on my rev it gives "3,1,2,6,4,5"
06:05kotarakThere was a change in size when array-map is used by {}, I think.
06:05Lau_of_DKthat might be it - anyway, Im inspired, thanks
06:36cgrand,(apply str (interpose "," (mapcat #(map % [:alpha :beta :gamma]) (list {:alpha 1 :beta 2 :gamma 3} {:alpha 4 :beta 5 :gamma 6}))))
06:36clojurebot"1,2,3,4,5,6"
07:57Lau_of_DKThanks alot cgrand
10:21RadioApeShotIs there a predicate which returns true for anything which produces a seq when passed to the seq function?
10:21kotarakcoll? might be a first guess.
10:22RadioApeShotAh
10:22RadioApeShotI was using col?
10:22RadioApeShotThat is just what I want
10:22RadioApeShotThanks
10:22kotarak#(or (coll? %) (seq? %))
12:46blbrownanybody there
12:47kotarakyup
12:47durka42indeed
12:47durka42nifty bus wi-fi
12:48hipertrackerDo Clojure have named parameters?
12:48blbrownI forgot how to do this. if I have ... (let [l some-list] (some-func (fn [line] (append to list)) ... a list and then some func appends to the list. How would I append to the list. Is it just append
12:48cmvkkconj?
12:49durka42hipertracker: yes, all parameters are named, except in anonymous lambda fns #( ... )
12:49cmvkk,(conj '(1 2 3) 4)
12:49clojurebot(4 1 2 3)
12:49cmvkkeh...
12:49blbrownhmm
12:49cmvkk,(conj [1 2 3] 4)
12:49clojurebot[1 2 3 4]
12:50kotarak,(concat (list 1 2 3) (list 4))
12:50clojurebot(1 2 3 4)
12:50kotarakThe use of a vector with conj is probably what you want.
12:51cmvkkthere's not a better way to append to a list than concat and wrapping the second argument in a list, I guess.
12:52kotarakI'm not aware of another way. If one needs to append, one should use a vector. If one needs easy adding at the end and simple retrieval at the front, one can use a PersistentQueue.
13:00rlbWhat position (if any) does clojure take wrt exceptions? For example, is it normal for clojure functions (built-in ones in particular) to throw exceptions?
13:02durka42exceptions are used kind of in the same way as java would
13:02durka42,(distinct?)
13:02clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$distinct-QMARK-
13:02durka42,(let [1 "one"] (prn "bad"))
13:02clojurebotjava.lang.Exception: Unsupported binding form: 1
13:03rlbOK, in part, I just wanted to make sure I understood how defensive you need to be in cases where it might matter. Thanks.
13:03durka42there is also chouser's error-kit in contrib
13:03rlbAlso, am I right in assuming that if you want your own type of exception, you would probably created it via gen-class, or is there some better way?
13:04durka42if you want it to have a distinct type that you can specify in a catch, then you have to gen-class it
13:04rlbOK, thanks.
13:18lisppaste8blbrown pasted "Mutate the vector" at http://paste.lisp.org/display/76622
13:19cmvkkif you want to mutate the vector
13:19blbrownI am assuming I need 'ref' I did this before but forgot the syntax. Is that the way to go
13:19cmvkkinstead of [] use (atom []), and then instead of (conj vec-line ...) do (swap! vec-line conj ...)
13:20cmvkkyou could use a ref too. but you're only working with one thing so either is okay.
13:20blbrownOK
13:20cmvkkoh and you have to use @vec-line to read it.
13:21blbrownI am using opennlp, pretty cool library and works flawlessly
13:22cmvkkwhat exactly is happening in that example, are you just looping through input, building that vec, then returning it?
13:22cmvkkbecause there's probably a way to do that without mutation...
13:23blbrownpretty much
13:23cmvkkyou might be better off with loop/recur for rebinding then, rather than mutation. But it's hard to tell from this viewpoint whether that would make simpler syntax.
13:24blbrownmaybe not even 'loop' but 'foreach' or whatever the call was
13:24cmvkkoh, yeah, for.
13:24cmvkkthat's true too.
13:24blbrownI still have a Java/imperative programming style.. I will get there eventually
13:25cmvkkclojure is a good language for learning to code this way, because at least it makes you realize you're using mutation when you do.
13:26blbrownyea, it is pretty obvious isn't it
13:26blbrownisnt like a = 3 , b = 4, a =3 in the imperative world
13:31zakwilsonIn Haskell, it's even more obvious. The mutation shows up in the type signature.
13:32zakwilsonYou *can* hide mutations in Clojure if you try. In Haskell, I'm pretty sure you can't.
13:32cmvkki thought there wasn't mutation at all in haskell.
13:32blbrownand Erlang pretty much has no mutations
13:32zakwilsonThere's the State monad.
13:32cmvkkoh okay.
13:33blbrownzakwilson, I am assuming you worked with Haskell, it is certainly a different style from clojure. Do you like both haskell and clojure and is there one language you would use for X task and one for another
13:33zakwilsonI have barely touched Haskell, but it really interests me.
13:34zakwilsonFrom what I know of Haskell, Clojure is better for getting things done quickly, but Haskell is better for knowing things about a program's correctness.
13:34ayrnieucorrectness with respect to types.
13:35zakwilsonYes, but but things have types in Haskell that don't really in other languages.
13:35zakwilsonAn IO action, for examlpe, shows up in the type signature of a function that uses it.
13:36blbrownzakwilson, good description
13:36ayrnieudoes that seem like a good example of something you'd want to check for the sake of a correct program?
13:37blbrownI think there is a world for clojure, haskell, scala
13:37blbrowns/world/architecture/g
13:37zakwilsonIn a formal sense, you could test that other ways if you're trying to prove a program correct.
13:38zakwilsonIn a real-world sense, I think it might reduce a programmer's error rate, but I haven't written anything non-trivial in Haskell, so I can't be sure about that.
13:39rlbDoes clojure have a clever way to define a function that has only one optional argument, and where providing additional arguments is treated as an error? I know I can just check the rest list...
13:39ayrnieurlb - define a multi-arity function.
13:39blbrowna good test framework is where you can prove correctness in a dynamic clojure world. But that takes a little extra effort, where I guess in haskell can be a little bit more automatic
13:39hiredman~def max
13:39rlbayrnieu: I saw that.
13:40ayrnieu(defn foo ([x] ...) ([x y] ...)) -- the lesser-arity function can supply the default value in a 'recursive' call to the greater-arity function.
13:40zakwilsonblbrown: I think it's just a matter of where the effort goes. In Haskell, it's up front, when you're writing the program.
13:40ayrnieuzakwilson - correctness with types is 'up front', and continuous.
13:40rlbayrnieu: ahh, I hadn't realized that the bindings allow them to call each other -- perfect.
13:40rlb(and quite nice)
13:41zakwilsonayrnieu: Yes. What I'm saying is that in Haskell, you have to spend more effort when you write the code, whereas with Clojure, the effort is moved to testing.
13:41blbrownand lets not leave scala out. If you are working with the jvm, I could see writing an architecture around clojure and scala. For example, I could see a web framework with clojure from fron end web application code and scala for database backend and server code
13:42ayrnieuzakwilson - you'll find that Haskell's type checking will be very useful indeed in Haskell, a language so opaque and horrible that you can hardly trust yourself to follow what your own idiomatically golfed code is doing. But to see how useful it is in general, just look at what you've been doing.
13:43digashblbrown: why do you see scala more useful for the backend then clojure?
13:43zakwilsonI see ayrnieu isn't a big Haskell fan.
13:44zakwilsonI've decided to learn it in an attempt to purify my mind after working on some really bad PHP. I don't know that I'll actually make a habit of using it.
13:45blbrowndigash, kind of what zak was saying. You want correctness up front when writing more mission critical code. Like your server backend. But for the web application server pieces. Say in the MVC model, passing the data to the view form, you don't need for your entire application to be correct up front. Hope that makes sense
13:46blbrowndigash, this is just my ad-hoc take on where I would use a more dynamic language like clojure and where I would use something like scala or haskell
13:46zakwilsonI think it's more a matter of... if you know exactly (or nearly) what you're going to make, more safety up-front is nice. If you don't, it may get in the way.
13:47ayrnieuzakwilson - that quote makes this more relevant: http://paste.lisp.org/display/75921
13:47blbrownand in a web environment, the more front end code, you are going to change what data gets displayed, what doesn't, etc, etc. Probably more often than the back-end layer.
13:48blbrownayrnieu, nice words of wisdom
13:54zakwilsonayrnieu: Very good, and I it illustrates well one of the things I think is wrong with Arc.
13:54blbrownoo, you messed with arc, im sorry
13:55zakwilsonI've done PHP for money. Arc was nice by comparison.
13:55blbrownI think PHP, VBBasic?, Perl are competing for the ugliest languages
13:55ayrnieublbrown - http://tnx.nl/php
13:56zakwilsonhttp://paste.lisp.org/display/76132 <-- and that wasn't the worst of it
13:56blbrownhehe
13:57zakwilsonI inherited a project that was PHP from a Ukranian sweatshop. I thought it would be quicker to refactor it than scrap it. I was wrong.
13:59blbrownactually, I did create a simple file upload system for my website. I guess for quick server side apps, it can be OK
13:59blbrownhttp://botnode.com/ for example, here, I can update all of the content through my php application
14:00blbrownhehe http://botnode.com/dev/app/octane_flowers.php
14:20arohnerare there any rules about code that has dependencies on third party jars going into contrib?
14:20kotarakarohner: there is already eg. miglayout. That also needs a third-party jar....
14:22arohner_kotarak: thanks
14:23kotarakarohner_: however I'm in no way authoritative! :) So you should make sure with rhickey or chouser, I guess.
14:30Chouserclojure.parallel is itself optional, but requires a 3rd party jar if you want to use it.
14:30Chouserand a couple of contrib libs require or can use a 3rd party jar
14:31Chouserso I guess there's no rule against it. :-)
14:43durka42does this already exist in clojure?
14:43durka42(defmacro comp* [outer inner] `(fn [& args#] (apply ~outer (map ~inner args#))))
14:43durka42i.e. ((comp* = first) [1 2] [1 3]) => true
14:47ChouserI don't think so
14:47rlbIs there already any easy way to "tap" a java FileOutputStream (so you can have a clojure function operated on all the data passing through it)?
14:47rlbs/operated/operate/
14:49rlbI suppose I could just change the way I'm handling the file copy (and processing). I started off using nio (a ByteBuffer) because I was under the impression that it's substantially more efficient and this is going to handle a *lot* of data.
14:52rlbA simple thing to do would be to change it so that the code just presents the incoming and outgoing data as seqs of binary chunks. That'd be much easier to manipulate from clojure, but it would also (I assume) result in quite a bit of extra copying.
14:53Chouserdurka42: another way: (defn comp*2 [a b] (comp (partial apply a) (partial map b)))
14:53Chouser((comp* = first) [[1 2] [1 3]])
14:54durka42ooh, that's better. less distance between thought and code
14:54kotarakand no macro :)
14:54durka42wonders*
14:58hiredmanrlb: you can proxy OutputStream an have it close over your FileOutputstream
14:59rlbhiredman: and I'd selectively override its methods (assuming I understand both what you're saying and how clojure's methods work)?
14:59hiredmanactually
15:00hiredmanI guess you could just proxy FileOutputstream
15:00hiredmanrlb: yes
15:00durka42define something as a macro, then try to redefine it as a non-tail-recursive function --> error
15:01hiredman~java_interop?
15:01clojurebotTitim gan �ir� ort.
15:01durka42~java interop is .
15:01clojurebotYou don't have to tell me twice.
15:01hiredman~java interop is http://clojure.org/java_interop
15:01clojurebotAck. Ack.
15:04rlbhiredman: I think, at least for read-only ops, and if I want to keep from having to make more than one copy of the data, that a quick, simple solution might be to add something like (for-each-chunk [func file] ...). The func would be passed the (same) ByteBuffer after each read. Then func could just be composed of as many ops as desired.
15:04hiredmanrlb: which ever way you want
15:04blbrownwatch this
15:04lightbotI am sorry, I did not understand
15:05blbrownhello
15:05lightbotHello, My name is light
15:05blbrownwhat is your name
15:05lightbotMy master goes by the nick, blbrown
15:05blbrownthanks
15:05lightbotI am sorry, I did not understand
15:05blbrowndo you want to play a game
15:05lightbotYes David, I like to play games
15:05blbrownHello my name is bob
15:05lightbotI am sorry, I did not understand
15:05hiredmanhaving the bot react to ever line in the channel may get old fast in here
15:05lightbotI am sorry, I did not understand
15:05blbrownHello my name is Bob
15:05lightbotMy name is light
15:05hiredmanyou might want to take it to #clojurebot
15:05rlbhiredman: thanks, though, I'll keep your suggestion in mind, esp if I want transformational ops later.
15:06blbrownhiredman, yea, just testing, I have my natural language parser hooked up to it
15:06hiredmaninteresting
15:06blbrownthat was verion 0
15:37rlbDoes clojure have anything like scheme's case or cond syntax, or is that sort of thing normally handled by other means?
15:37cmvkkcondp maybe
15:37cmvkkand cond
15:38rlbSorry, I overlooked it in the docs -- thanks. I was looking on the doc page with if, do, etc...
15:47rlbIs tree-seq guaranteed to traverse the children in the order provided by the provided func by any chance?
15:47rlb"the children func"
15:48rlbAt least in this case, that woud be very helpful.
15:48gnuvince_"the children func"... I'm sure this could get you arrested.
15:49cmvkkit seems like it would from the function def
15:53rlbcmvkk: it does seem pretty likely. Though since it's critical, I suppose I can insert some (obviously non-exhaustive) build tests, just to make sure it doesn't appear to change in future versions of clojure.
15:54RaynesIs there a function that takes 2 seqs and interweaves them like giving it (1,3,5,7) (2,4,6,8) would make (1,2,3,4,5,6,7,8)?
15:54cmvkkor since the def is only 5 lines long anyway, you could just copy it into your own source and control it that way.
15:54cmvkkinterleave
15:54RaynesHawt thanks.
15:54cmvkk,(interleave [1 3 5 7] [2 4 6 8])
15:54clojurebot(1 2 3 4 5 6 7 8)
15:54rlbcmvkk: true -- I was thinking about that.
15:55rlbcmvkk: I should probably check out the clojure source.
15:57cmvkk~def tree-seq
15:59Raynes(defn children-func [num names] (apply hash-map (interleave num names))) <--Children function.
16:00durka42bah i'm sorry for all the bouncing
16:00durka42sketchy w-fi
16:00durka42wi-fi
16:08djkthxhmm
16:09djkthxim getting a strange error
16:09djkthxwhen i start emacs
16:09djkthxAn error has occurred while loading `/Users/ynadji/.emacs':
16:09djkthxFile error: Cannot open load file, clojure-auto
16:09djkthxbut i have the path to clojure-mode added in my ~/.emacs
16:09djkthxit's new after i switched to the google code clojure
16:11djkthxnevermind
16:11djkthxgot it working
16:19rlbDoes java have anything like (.isLink file) -- or more specifically, a (perhaps platform specific) way to get essentially all the information about a file (is it a socket, character device, etc...)?
16:21rlbWow, so far, it looks like not (dating back to even 2001). If so, that's surprising... (to put it mildly).
16:23p_lrlb: by creating a cross-platform library, you either do it all-inclusive or lowest common denominator. Java had gone for the latter.
16:23p_lCommon Lisp's pathname system is example of the former :)
16:24rlbOK, though if that's true, then I either just can't write the app I was working on in clojure, or I'll have to call out to a C or python helper application.
16:24rlb...and if so, that's really too bad.
16:25rlbI suppose python might be the most portable thing.
16:29rlbOf course then the first FAQ entry will be "Q: why didn't you just write it all in python."
16:31hiredmanhttp://www.idiom.com/~zilla/Xfiles/javasymlinks.html
16:31rlbhiredman: yeah, that's *very* disappointing.
16:32rlbI need everything, "is it a special file, is it a character device, what's the major and minor for the device, etc.".
16:32rlb(on unix at least)
16:32rlbI may need to re-think.
16:32p_lrlb: Check if there's low-level OS support library
16:33rlbp_l: right -- I'm going to look around a bit more.
16:34rlbp_l: I'm also starting to wonder if I might be able to just create something myself via JNI (or whatever), if necessary.
16:34p_lrlb: You might want to look at swig, then
16:35p_lI just lost a night playing with it :)
16:35rlbp_l: I have. I've used it for that before, though I may also want to see just how hard it would be to do it without the added dependency.
16:35p_lheh
16:36p_ljust generate the bindings and you probably wouldn't need swig anymore, except maybe as compile-time dependency
16:36rlbI wonder if it would be feasible/useful to create some kind of clojure support for JNI wrappers.
16:38rlbI suppose messing with JNI directly is probably one way to figure that out.
16:38cp2rlb: you would just need a normal java class with native method definitions
16:38cp2you can do the rest from clojure
16:39rlbcp2: I was more thinking of some way to do something like what swig does, but from clojure. Perhaps not worthwhile, but i was just wondering...
16:39cp2yeah, i dont really know
16:39AWizzArdrlb: I think there is all you want. Check out http://openbook.galileodesign.de/javainsel8/javainsel_14_001.htm
16:39AWizzArdThis is in german, but anyway, just read the code and check the output
16:40AWizzArdListing 14.2 ShellFolderDemo.java shows how you find out if something is a link
16:42hiredmanAWizzArd: he wants to be able to tell if a file is a character device
16:42dreishI haven't tried it, but jtux looks like a good general solution.
16:43dreishIt provides access to all the POSIX syscalls.
16:43abrooksrlb: I posted a JNI example a while back... let me find it.
16:43abrookser..
16:43abrooksJNA
16:43rlbdreish: haven't tried what?
16:44dreishrlb: jtux
16:44abrooksrlb: http://groups.google.com/group/clojure/browse_thread/thread/77e626c5440bf1a0
16:44rlbdreish: oh, right.
16:44abrooksdreish: jtux seems mostly dead.
16:44dreishabrooks: Maybe they got it right 3 years ago and haven't had anything to fix. ;-)
16:45rlbabrooks: ahh, so jna is java libffi-ish?
16:45rlb(I think I knew that...)
16:46abrooksdreish: Possibly, but my experiences with software say "No." ;-D
16:46abrooksrlb: Yes.
16:46dreishMore recently-updated: Posix for Java at http://www.bmsi.com/java/posix/package.html
16:46durka42Jtux supplies two non-standard functions, jaddr_to_seg and jaddr_from_seg to copy data between pointers represented as longs and Java byte arrays.
16:46durka42uh oh - pointers for java
16:47abrooksdreish: Ah, that's cool. Thanks for the link.
16:47cp2durka42: there is already somethign similar to that in the jdk
16:47cp2the class name is Unsafe
16:48cp2and lets you set/get data based on memory address
16:48cp2its one of those evil hidden classes :)
16:49cp2ezbake fed trials
16:49rlbdreish: ahh, ok, that's interesting, and at least judging by the file mod times, it looks active.
16:50rlbThanks all -- I think I'll look in to java posix a bit further. If that works out, I'll just plan to help the upstream there.
17:10rlbdreish: that was easy, and so far, it appears to work. It also doesn't look like it would be difficult to extend.
17:11rlbexcellent.
17:11dreishrlb: Thanks, I'm glad to hear it. I think I'll want to use it too at some point.
17:11dreishThis was the one at bmsi.com?
17:11rlbdreish: yes.
17:14rlbHmm -- wonder about adding a debian libposix-java package. I suppose for now if it works out, I'll probably just plan to include it, but later...
18:14arohnerclojurebot: paste
18:14clojurebotlisppaste8, url
18:14lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
18:14Chouserheh
18:34harry__ /past
18:39rajarshiHi, a lisp newbie here and I had a question regarding loop, When using loop and recur to build up a list, how do I return the result of the last iteration? I'm always getting nil
18:41cmvkk(if (end-of-loop) result (recur (add-to-result) ...)) for example?
18:41cmvkkwhere you'd have a test for the end of the loop etc
18:41rajarshicmvkk: ahh, missed the obvious solution. Thanks
18:56Lau_of_DKGood evening folk
18:56Lau_of_DKAll but the americans have gone to bed ?
18:57keithbAll, what is the best way to pass key/value pairs to a function? Should I use (hash-map ...) to package them into a single map?
18:57keithbOr, is there some kind of syntactic sugar like in Ruby, where I can just pass key/value pairs literally?
18:57Lau_of_DKI'd say it depends on the purpose
18:58cmvkkarglists for functions can do all sorts of map restructuring if you want to do that
18:58cmvkkdestructuring, more like
19:00keithbI'm writing a function that creates and returns a subclass of AbstractAction. I'd like to be able to be able to pass key/value pairs for its properties (tooltip, accelerator key, etc.) into this function.
19:00keithbThere are several of these options, and I don't want to hard code any of them.
19:03Lau_of_DKI'd go with one hash-map
19:05hiredmanclojurebot: destructuring?
19:05clojurebotdestructuring is http://clojure.org/special_forms#let
19:05keithbLau_of_DK: Thanks. It is a pretty clean way to go.
19:08Lau_of_DKYea I think so
19:16digashi see in the gen-class doc that if i add to a signature a #^{:static true} it should generate it as static, but it does not
19:17digashanybody has any example with static generation?
19:18mgarrissif i have a list of maps how do i increment some key within each map and return the coll? example: (foobar ({:x 0} {:x 0} {:x 0})) ; => ({:x 0} {:x 1} {:x 2})
19:21cmvkkso every map has 0 as the value of the key already?
19:21mgarrisseach starts with :x set to 0
19:22cmvkk(map (fn [mp nv] (assoc mp :x nv)) map-list (range (count map-list)))
19:23cmvkkyou're mapping over each map, and applying the value of an incrementing number to some specific key.
19:24mgarrissthx. new to clojure, this is still hard to understand
19:25gnuvince_,(map #(update-in %2 [:x] %1) (map #(fn [x] (+ x %)) (range 3)) [{:x 0} {:x 0} {:x 0}])
19:25clojurebot({:x 0} {:x 1} {:x 2})
19:28cmvkkyeah, that's more general than mine. It'll add an incrementing number to the value of :x whether it starts with 0 or not.
19:29gnuvince_Yours is less horrible though :)
19:29cmvkkwhenever i try to type 'closures' now, i always accidentally type 'clojures'
19:29gnuvince_I have a map with an anonymous function to generate an anonymous function ;)
19:30gnuvince_cmvkk: tell me about it.
19:31hiredmanI wish rhickey would commit something
19:31mgarrissnow i get it, i didn't realize that map could take multiple collections
19:31cmvkkyep. the number of collections is equal to the number of arguments in the map function.
19:32gnuvince_hiredman: like what?
19:32gnuvince_mgarriss: yeah
19:32hiredmananything, I want to see if clojurebot's svn log -> twitter bit is working
19:32gnuvince_hiredman: don't you have mock objects to test that? *wink*
19:32cmvkki was about to say...
19:33cmvkkreal world testing is hard, you're supposed to be simulating this stuff.
19:33replacaQ: Is replicate being dropped in favor of repeat
19:33replaca?
19:34gnuvince_mgarriss: Clojure has only map which can work with a variable number of arguments. If you know Haskell, you probably know zipWith through zipWith8
19:34hiredmanI have dones some tests, and they worked
19:34hiredmanbut I will not be sure it works until it is doing what I want it to do
19:36cmvkkreplaca: they do seem to do the same thing. isn't it sad? replicate is the function closest in name to your handle.
19:37replacacmvkk: I don't think repeat used to be there, and I thought I saw some comment that made me think that Rich was changing it over, but I was working on something else. I like repeat better, my handle aside. :-)
19:37lisppaste8keithb pasted "Maps" at http://paste.lisp.org/display/76643
19:38keithb_I guess it's a little simpler to specify the { } literal ArrayMap rather than (hash-map ...), all other things being equal, and for a very small map?
19:39hiredman,(class {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9 :i 10 :k 11 :l 12 :m 13 :n 14})
19:39clojurebotclojure.lang.PersistentHashMap
19:40ayrnieu,(take 5 (repeatedly #(repeat 2 (rand))
19:40clojurebotEOF while reading
19:40hiredmanI think after nine items arraymaps are auto magically turned into hashmaps
19:40ayrnieuso I prefer 'repeat' to 'replicate'.
19:43keithb_hiredman: Interesting, thanks.
19:43replacaahh, issue 55: remove replicate in favor of repeat with multiple arities
19:44hiredmanwell, repeat already has replicates functionality, it just hasn't been removed
19:44replacayeah, I'm just trying to future-proof my code right now, so I guess I should remove all the replicates
19:45ayrnieuwishful thinking :-)
19:46replacawell, yes, but in this case it would help :-)
19:46replacaI'm generally in the midst of adapting cl-format and my pretty printer to the "lazy" world, which is a big code walk anyway, so I'm getting anything I can along the way
19:50digashi've got it, was putting static in the wrong place
19:50digash:methods [#^{:static true} [suite [] junit.framework.Test] is the right way
19:51digash:methods [[#^{:static true} suite [] junit.framework.Test] ; not this way :)
20:01lisppaste8arohner pasted "defn-memoize" at http://paste.lisp.org/display/76644
20:01arohneris that a good idea?
20:02arohneris there a cleaner way to write that?
20:05cmvkkwell, does that work?
20:05arohnerit works
20:05arohnerjust looks like it could be prettier
20:05hiredman`(def ~name (memoize (fn ~@body))
20:05cmvkkthere's that too.
20:06cmvkkyour version will choke on docstrings maybe though
20:06arohnerright.
20:06ayrnieuand for multiple-arity defns?
20:06cmvkkit'll work for that.
20:06cmvkkfns do that just like defn.
20:08replacawell docstrings would work with ^#{:doc "xxx..."}
20:08arohneryeah, but you're losing half the reason of having defn
20:08replacabut that's not fully defn-style
20:09cmvkkcan defmulti take docstrings yet?
20:09cmvkkah, it can.
20:09ayrnieuarohner - your verison is fine.
20:10arohnerayrnieu: thanks
20:14arohnersince clojure is immutable, you can test to see if two arrays are equal just by comparing pointers, right?
20:14replacano
20:14replacaobjects aren't "interned"
20:15replacaso you can have [0 1 2] and [0 1 2] as two separate things
20:15cmvkkequality is defaulty by value.
20:15cmvkkidentical? will work that way though...
20:18replacayou might be confused because some languages (Java, I think) use immutable strings and "intern" them so the same string will always be the same object. But that generally isn't true of immutable objects in other environments
20:21ayrnieuLua and Pike do that.
20:21hiredman,(= "foo" (String. "foo"))
20:21clojurebottrue
20:23ayrnieu,(identical? "foo" (String. "foo"))
20:23clojurebotfalse
22:44brennanctrying to figure out how to connect to mysql through clojure. I'm import clojure.contrib.sql and then did (with-connection {:user "root", :subname "localhost", :classname "com.mysql.jdbc.Driver", :subprotocol "mysql"} (println "test")) but it says "jaa.sql.SQLException no suitable driver"
22:44brennancit's in the classpath and I can do (Driver.) and it creates an instance fine so I'm not sure what the problem is. Any ideas?
22:45Chouserhttp://stackoverflow.com/questions/613929/how-do-i-connect-to-a-mysql-database-from-clojure
22:47brennancthanks, will try that
22:47ChouserI think it's step 2 that you may be missing
22:47Chouserthe -D thing
22:48brennancjust tried it without step 2 and it seems to work
22:48brennancI had the subname as "localhost". I needed to set it to "//localhost" for it to work
22:48Chouseroh, ok
22:49brennancreally weird. never heard that term before and it's weird to require the // in front
22:49brennancoh well, easy enough, just gotta know that I guess