#clojure logs

2010-02-06

00:00BrandonWi have another question :) i don't understand the difference between commute and alter. what is the difference between restarting a transaction, and re-running your function with the newest value of the ref you are changing?
00:01BrandonWand if commute doesn't care about in order processing, but alter does: don't they both work such that whichever operation on the ref finishes first is the first one that succeeds in changing the ref? how is commute different from alter in terms of ordering?
00:03alexykliebke: ping?
00:15liebkealexyk: hey
00:16alexykliebke: is there a paper I could cite for Incanter? Otherwise I did this: http://paste.pocoo.org/show/174472/
00:17liebkealexyk: that looks fine, I'm looking forward to reading the paper.
00:17alexykliebke: cool
00:23JayMhmm..possible to get out of an infinite loop in slime?
00:25somniumJayM: C-c C-c
00:27JayMsomnium: aha, thanks
00:33slyrusevening
00:34slyrusso... I see that clojure-contrib has switched over to maven. how do I use maven to build a clojure-contrib jar without downloading all sorts of crazy jars from god-knows-where?
00:45alexykliebke: I have two lists, xs and ys, I feed to scatter-plot. How do I save them to disk to get them back readily to reproduce scatter-plot?
00:45alexykneed to reload with your pdf option
00:46liebkealexyk: create a dataset from the two vectors and save it with the save function
00:47liebke(save (conj-cols xs ys) filename)
00:48alexykok
01:06alexykliebke: and how do I load it back and feed to scatter-plot again?
01:09liebkealexyk: (scatter-plot :col-0 :col-1 :data (incanter.io/read-dataset filename :header true))
01:10alexykliebke: for some reason conj-cols wasn't available, I did (matrix [x y]) -- how do I read *that* back?
01:10alexykx and y are vectors of x's and y's
01:11liebkealexyk: you might have an old version. incanter.io/read-dataset works with saved matrices too
01:12alexykin the same way? are x and y columns then?
01:12liebkealexyk: check the saved file though, x and y are probably rows the way you created the matrix
01:12liebkeuse trans to flip them
01:12liebkei recommend updating incanter too
01:13alexyktmrw :)
01:13alexyk(after the 3 am deadline)
01:13alexykis there a :row-0 etc selector?
01:13liebkewhat time is it where you are?
01:14alexyk1:14 am
01:14liebke(sel :rows 0)
01:14alexykok
01:14liebke(sel mat :rows 0)
01:15liebkealexyk: ah, you're in my timezone, where are you?
01:15alexykliebke: Dartmouth
01:15liebkeah
01:15alexykthink Moose
01:16fatrowhi. Is there a way to get a subsequence like a slice of python?
01:20qedexec("/bin/kill $blah_pid[0] 2>&1",$a,$b);
01:20qed^^what is happening here?
01:20qedwhat is the 2>&1 is that just sh script?
01:20qedim trying to understand that line
01:21krumholtfatrow, something like split-at?
01:21krumholt,(first (split-at 2 [1 2 3 4]))
01:21clojurebot(1 2)
01:21krumholt,(second (split-at 2 [1 2 3 4]))
01:21clojurebot(3 4)
01:24fatrowkrumholt: thank you.
01:29krumholtfatrow, or if you need more arbitrary splits you can use a combination of drop and drop-last
01:30krumholt,((fn [coll x y] (drop (dec x) (drop-last (- (count coll) y) coll))) [1 2 3 4 5 6 7 8] 3 5)
01:30clojurebot(3 4 5)
01:31fatrowkrumholt: thanks. I want to get a subsequence like (xxx [1 2 3 4] 1 3) => [2 3]
01:32krumholtyes my last post will do exactly that
01:32fatrowkrumholt: thank you.
01:33krumholtok not exactly that it starts at index 1 not 0
01:37fatrowI guess subseq is this, but it is different.
01:39krumholt,(subvec [1 2 3 4 5 6] 2 4)
01:39clojurebot[3 4]
01:42fatrowkrumholt: oh, subvec is this. Is there a subvec for general sequence version ?
01:43krumholtfatrow, i am not sure. but it is not subseq :)
01:43krumholt,(subs '(1 2 3 4) 2 3)
01:43clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.lang.String
01:44krumholt,(subs "blub" 2 3)
01:44clojurebot"u"
02:28fatrowkrumholt: I have solved it. thanks.
02:28fatrow(defn slice [coll start & end] (let [len (count coll), start (max start 0),end (if (nil? end) len (min end len))] (take (- end start) (drop start coll))))
02:30zabIs it worth attempting to shoehorn an installation of Clojure on App Engine?
02:31hiredmanyou don't need to shoehorn
02:31hiredmanit's fairly painless
02:31zabwhat about loss of language features like concurrency?
02:32hiredman*shrug*
02:32zabhmm ok
02:33zabim fairly new to the whole JVM thing, but will give it a shot. any good resources out there particularly suited to GAE?
02:33hiredmanhttp://github.com/zitterbewegung/blank-appengine-clj
02:33hiredmanlooks good but I have no experience with it
02:34zabnice thanks!
02:34hiredmanI have http://github.com/hiredman/appengine-helper but I am not regularly working on it, and it is slowly bitrotting
02:35hiredmanthere are some nice blog posts around
02:35zabyeah i've read most of them i think. they are all pretty old though.
02:37hiredmanappengine-clj was junk last time I looked at it, which was many moons ago
02:37hiredmanI really like google's datastore
02:37hiredmanmaps well to storing maps
02:39hiredmanI did two apps on appengine, really small facebook apps (maybe five users tops)
02:39hiredmanmostly just for my personal use
02:40zabive built a couple of python GAE apps. i really like the model and pricing structure.
02:40zaband i want to pick up a new language, and clojure looks really interesting.
02:40zabive never really dug into a lisp before.
02:41hiredmanrunning clojure on the appengine does mean you have to monkey around with AOT compilation
02:42hiredmanat least for the servlet file
02:43hiredmanthe gen-class stuff can be painful to work with
02:43zabis this in the clojure documentation, or is this JVM stuff? (like I said, new to JVM)
02:44hiredmanit is under compilation
02:45hiredmanthe java appengine follows some java webapp spec "servlets" so you need to generate a class with a stable name that the servlet stuff can talk to
03:52Lewishamhi all, Clojure newbie here. I'm trying to do a simple recursive movement through a list, and it's not going well :) I keep getting an NPE thrown out, and I'm not sure what I'm doing wrong. It's very basic! http://pastie.org/812186
03:52LewishamI'm also not sure if I'm doing things the Clojure way
03:52Lewishamso any help would be appreciated
03:53hiredmanyou have an extra pair of parens
03:53LewishamI do? I thought they all matched up :/
03:54hiredmanyes
03:55hiredmana form like (a b) is function application
03:55hiredmanyou have ((println ...) ...)
03:56Lewishamoh, I see
03:56LewishamI didn't need to wrap the second clause in parens
03:56Lewishamd'oh
03:57hiredmanif takes two forms
03:58hiredmanhttp://clojure.org/special_forms#toc12
03:59hiredman,(reduce (comp inc first list) 0 '("one" "two" "three"))
03:59clojurebot3
04:00hiredman,(count '("one" "two" "three"))
04:00clojurebot3
04:00IntertricityHow close is ClojureCLR to binary?
04:01hiredman"close to binary"
04:01Intertricityand, how do you access a C# dictionary from it >.> or can you
04:01Intertricitywell it's via compile only atm :P
04:01hiredmanso?
04:02hiredmanwhat does that have to do with binary?
04:02Lewishamhiredman: thanks very much :) I got it to work with (do...)
04:02LewishamI need to figure out how this recur form works though
04:02Intertricityhiredman, I'm assuming they'll make a binary for more public use when it's mature enough
04:02hiredmanbinary is a counting system using two digits
04:02Intertricityohh, no I meant compiled already
04:03Intertricitydrop in and go
04:04hiredmanso you meant to ask "how close is ClojureCLR to being distributed already built?"
04:05Intertricityyes, sorry, that would be a better way to put it
04:07hiredmanhard to say, I don't know how much of a community it has, and community feedback tends to drive releases
04:55Lewishamhi, sorry, another silly question :) is there a way I can have (count-words) initialize "bins" if it's nil? I've been Googling for things like "default arguments clojure" and it's returning some scary key based stuff that I don't yet understand! http://pastie.org/812204
04:58lypanovyou could use the multiple function defn form
04:58lypanov(defn blah ([x] first fun) ([x y) second fun))
04:59Lewishamoh, that's true
06:20StartsWithK(time (dotimes [i 100000] (keyword (str "x" i)))) -> "Elapsed time: 2495.639935 msecs", but (time (dotimes [i 100000] (clojure.lang.Keyword/intern (str "x" i)))) -> "Elapsed time: 357.043285 msecs"
06:20StartsWithKwhy such a big difference?
06:21StartsWithKit looks like keyword checks for Keyword instance, and it wastes time on that
06:39ChousukeStartsWithK: an instance check shouldn't take that long :/
06:39StartsWithKhttp://paste.pocoo.org/show/174527/ i am trying to speed up my json lib, and by using Keyword/intern i get something like 4x speedup in reader (words was slurped from cca 330kb json file)
06:40StartsWithKlets see how it works on c.c.json
06:46StartsWithK~2x speedup in c.c.json when using Keyword/intern vs keyword
08:00qedmorning gents
08:03AWizzArdHallo qed
08:13qedAWizzArd: top 'o the mornin' to ya
08:13qedAWizzArd: how goes clojure?
08:14AWizzArdGoing good so far, today I will be hopefully finishing my db transactions as the underlying mechanism for manipulations.
08:14qedinteresting -- i dont know what you're talking about :)
08:15qedAWizzArd: how does it work
08:15AWizzArdThe DB system I am writing in Clojure for Clojure.
08:15qedare you using the STM as your DB, or something more heavy duty?
08:15qedAWizzArd: ahh, very cool
08:15AWizzArdI thought you mean this when you asked how it is going :-)
08:16qedah, sorry :)
08:16AWizzArdUnder the hood it does not use the STM, but the data structures rhickey implemented, which are amazingly powerful and useful for such work.
08:17qedso clojure's standard structures? vec/map/set/etc?
08:17AWizzArdYes. Because they are persistent.
08:17qedAWizzArd: would it be reasonable to build a DB on top of the STM?
08:18qedor rather a layer of DBness on top of the STM?
08:18AWizzArdI wanted to do that first. But the current dosync does not allow the use of "plugins". If you want to synchronize DB changes to disk it must happen in a dosync block.
08:18qedfrom what i gather about STMs in general -- they behave like databases, and I wondered if one could use that with some tinkering, as a production DB
08:19qedAWizzArd: i see
08:19AWizzArdBut a dosync should not contain side effects/io. Also for a DB one needs to do a guaranteed write to the disk, which will slow down each dosync and may trigger hundreds of unsatisfying retries.
08:20qedAWizzArd: yes my next question was about retries, but the i/o is another excellent point
08:21qedi am desperate to have some more time with clojure -- i have been so busy with other things lately
08:22AWizzArdThe real usefulness is that Clojures data structures are fully persistent, as in http://en.wikipedia.org/wiki/Persistent_data_structure
08:22qed*nod* yes
08:22qedtries -- bagwell
08:23qedAWizzArd: i was so...amazed...when i first learned about persistence in clojure
08:23qedi knew nothing of persistence prior to that
08:24qedshared structure -- versions of a structure, it's so elegant
08:39qedso much stupid in PHP it's unbelievable
08:39qedI really love this community
08:39qed#php, that is
10:08raekhow does relations work in clojure.set?
10:09raekcan someone show an example of how clojure.set/index is used?
10:25raekok, found something: http://www.mail-archive.com/clojure@googlegroups.com/msg17047.html
11:12npoektophi! can anyone help me with compojure? It looks a really simple question, but i can't find the answer myself.
11:12npoektophi! how do i get content of a POST request? I can do defroutes with (POST "/:name" ...) or smth and get that name with (params :name). But how do i get the whole content?
11:20LauJensennpoektop: check out my blog, have a few examples
11:20LauJensenhttp://www.bestinclass.dk/index.php/2010/02/reddit-clone-in-10-minutes-and-91-lines-of-clojure/
11:20LauJensenThis one is quite easy
11:25npoektopLauJensen: oh, i now i get it. (GET "/*" ...) and (params :*). Cool. Thank you.
11:25LauJensennp
11:38Rayneshttp://force7.de/nimrod/ Looked a little bit interesting until I found out it's written in FreePascal. What's up with that? :o
11:39patrkrisLauJensen: Is the new front-end in a state where I can test it, or is it currently b0rken?
11:40patrkrisLauJensen: talking about clojureql, if you were wondering :)
11:40kotarakpatrkris: not ywt
11:40kotarakyet
11:41patrkriskotarak: Ok. I checked out the frontend-2.0 branch. I like the new stuff (also from what I can read on gitorious). I'm excited :)
11:41kotarakthanks :) let's see how it works out.
11:42kotarakThere are quirks, but there are also a lot of improvements
11:42patrkriskotarak: I saw that somewhere in the source code it says "Monad stuff". I've never understood monads, but I think I might go try to work on my understanding of it now.
11:42kotarakit uses now a state monad.
11:43patrkriskotarak: my impression is that frontend-2.0 keeps the promise of being more clojure-like instead of SQL-like
11:43kotarakgood for boilerplate, bad for dynamics
11:43patrkriskotarak: yeah... I have really no idea what it is. I've asked one of the PhD-students at my university to explain it to me, which he hopefully will soon.
11:44kotarakI try to get away from sql, I have working fleetdb prototype
11:44patrkrisbut i'm amazed that even some of the more senior scientists at my department aren't able to explain monads
11:44kotarakpatrkris: it is overrated
11:44patrkrismonads are overrated?
11:44Chousukepatrkris: The most simplified description of monads I can think of is that they describe how to compose operations
11:45kotarakyes, they are not a silver bullet
11:45patrkrisChousuke: yes, I've read that somewhere - but still ... :)
11:45Chousukepatrkris: so that two sequences of operations composed under a different monad have a different outcome.
11:45patrkrisChousuke: ah
11:45AWizzArdlypanov: because it can return the coll
11:45AWizzArd,(doc not-empty)
11:45clojurebot"([coll]); If coll is empty, returns nil, else coll"
11:46kotarakpatrkris: eg. i have to introduce non-sensic redirections to make the monad stuff independent from the backend
11:46lypanovAWizzArd: ah, k. now it makes sense. thank you!
11:46AWizzArdIt does not return true or false.
11:46Chousukepatrkris: this only applies to operations that can be "lifted" to the monad though. some operations might be such that they only work within a single monad :/
11:46lypanovstill think its weird that "empty" is so different to "not-empty"
11:47patrkrisChousuke: Ok. Did you go through category theory to understand them?
11:47kotaraknot-empty is a sister to seq
11:47Chousukepatrkris: nah.
11:47Chousukepatrkris: I've just read loads of monad tutorials. and I'm still not sure if I understand them
11:47lypanov(defn two-of-each [xs] (let [x (first xs)] (if (not-empty xs) [] (concat [x x] (recur (rest xs))) )))
11:47Chousukepatrkris: this is just my interpretation
11:48lypanovanyone have a clue why this isn't accepted? what does "recur must be in tail position" mean exactly?
11:48patrkrisChousuke: hehe, well that's what I've tried to do too, but probably not hard enough
11:48lypanovi guess i need a more specific form than this, i've used it a few other times without issue.
11:49Chousukepatrkris: I think the principles behind monads are simple enough, but it's so abstract that it's difficult to see how to apply it to a real problem :/
11:49lypanovah... got it.
11:49lypanovconcat is in tail position?
11:49Chousukelypanov: recur is in the tail position of the concat form, not the defn form :)
11:52kotaraklypanov: (defn two-of-each [coll] (mapcat (juxt identity identity) coll))
11:53lypanovooo. identity is cute.
11:55qedChousuke: you can have a recur without an explicit loop form
11:56Chousukehm?
11:56qedgah i just reformatted -- it's in stuart's book
11:57kotarakfn also adds a "loop" point for recur
11:57qedkotarak: thank you
11:57ChousukeDid I say something that hinted otherwise? :/
11:57qedi think i mis-read -- sorry Chousuke
11:58kotarakChousuke: maybe it was a question?
11:58qedi just saw recur .... not the defn form
11:58qedwhich means! it's time for bed. night all
11:59lypanovheh. night qed :))
12:13StartsWithKhow can i test is my pom.xml file correct without maven/lain/other build tools..
12:13StartsWithKis there a validator tool?
12:13StartsWithKand, how do i declare dependency on clojure 1.1-1.2-SNAPSHOT
12:16kotarakStartsWithK: [1.1,1.2-SNAPSHOT]
12:16StartsWithKdo i declare my lib alpha/beta?
12:17StartsWithKif it depends on 1.2 (alpha) shouldn't then that reflect my version too?
12:17StartsWithKi can't be 'stabel' if i depend on something that isn't?
12:32arkrosthi! Can anyone explain how to use dotimes macro with several bindings?
12:37the-kennyarkrost: Looks like dotimes only support exactly one binding
12:42AWizzArdone can easily stack them, or use for
13:13AWizzArdrhickey: did you hear/read from Mark Tarvers (teamed up with Carl Shapiro) effort to make the important parts of Qi available in such a way, that it can be ported to Clojure without too much work?
13:14AWizzArdMessage-ID: <37b52400-6e4f-4a15-8bd9-bb7b45ea8a40@14g2000yqp.googlegroups.com>
13:58BrandonWi have another question :) i don't understand the difference between commute and alter. what is the difference between restarting a transaction, and re-running your function with the newest value of the ref you are changing?
13:58BrandonWand if commute doesn't care about in order processing, but alter does: don't they both work such that whichever operation on the ref finishes first is the first one that succeeds in changing the ref? how is commute different from alter in terms of ordering?
14:08LauJensenYou pretty much said it. Commute doesn't enforce strict ordering, so you need to work on operation which arent dependant on the order, for instance incrementing, alter does enforce strict ordering, so moving items from 1 datastructure to another will maintain integrity, ie. the order in which the items were listed in list #1
14:12BrandonWwell, for example consider a chat application where a message log is being modified from multiple sources. the most recent message would appear at the top. i would consider that to be dependent upon ordering
14:13BrandonWhowever, i don't understand the difference between commute and alter there. in either case, whichever operation finishes the transaction first is the one that successfully modifies the message log
14:14BrandonWi don't understand what the difference between alter's need to restart the transaction if the value the ref is pointing at changes, versus commute's ability to just rerun the function without restarting the transaction (isn't that all the transaction is, just running the function on the most current value of the ref?)
14:18zaphyrbut the restart may cause your transaction to decide it should not continue
14:19BrandonWohhhhhhhhhhh
14:19zaphyrwhereas with commute, it cannot fail
14:19hiredmaneh?
14:20zaphyrchat logging is a bad example- imagine credit/debit transactions on a bank account, or similar
14:20BrandonWokay that is a much better example
14:20zaphyrhiredman: have i misunderstood the difference between commute/alter myself? :/
14:20BrandonWone transaction aims to debit $50, the other wants to debit $45, the account has $55 total
14:21BrandonWwell
14:21BrandonWso you can't have validation or anyting preventing a commutative transaction from continuing?
14:23BrandonWordering seems to be the main difference between alter & commute, but the order seems like it would stay the same no matter which function you use to modify the ref
14:23hiredmanthe credit/debit is better than logging because for stm examples it is best to have at least two refs
14:24hiredmanbut it is not good enough because you are still doing addition and subtraction
14:24hiredmanwhich are communicative
14:24zaphyrhiredman: yeah. agreed :)
14:24hiredmanLauJensen's example was pretty good but not fleshed out
14:25hiredmanif we have two refs, A and B, A points to [1 2 3] and B points to [4 5 6]
14:27BrandonWokay i think i understand now
14:27BrandonWi was thinking in terms of operations too simple (and coincidentally commutative)
14:27Chousuke"alter" is always the safe choice
14:27hiredmanalter?
14:27clojurebotalter is always correct
14:28BrandonWso it is more along the lines of if you have several actions that have to be done in a certain order, you can start the action via several alters, but as long as yuo start them in order you know they will be finished in order
14:28Chousukeyou can use commute if you notice that you're getting unnecessary restarts :)
14:28BrandonWwhereas if you use commute, even if you start them in order, the 3rd one might finish first, then the 5th, then the first, etc.
14:29BrandonWokay i definitely understand now... alter seems closer to synchronous, because if you have several actions, the quick ones might be much easier to execute, but they are at the end. so you would have to finish the first ones (which might be longer running) first
14:29ChousukeI'm not sure if that's quite right.
14:30zaphyrspecifically commute works only for commutative operations- that is X op Y == Y op X
14:30zaphyrno matter what order you evaluate a sequence of commutative operations, the result will always be the same
14:30BrandonWwell, consider a problem where you have several operations that have to be done in order. the first operation takes X time to complete, the 2nd takes x+1, the third takes x+2
14:30hiredmanBrandonW: if they are running concurrently the short transactions will complete and cause the longer running ones to restart
14:30BrandonWso all the actions try to execute at first, but every one but the first theoretically will complete before the first, but they would all have to restart because the first one wasn't done yet
14:31BrandonWand then again with teh 2nd, then again with the third
14:31hiredmanSTM is not a lock
14:31Chousukeno, the first one would restart if the second finishes first :/
14:32BrandonWokay i still don't understand the ordering concept then :(
14:32hiredmanclojurebot: the STM is not a lock
14:32clojurebotIn Ordnung
14:32hiredmanclojurebot: stm?
14:32clojurebotNo entiendo
14:32zaphyrxD
14:32hiredman:(
14:32hiredmanclojurebot: the stm
14:32clojurebotthe STM is not a lock
14:32Chousuketransactions are not ordered, but the operations within one transaction are
14:32BrandonWoh ok
14:32Chousukeunless you use commute, in which case it eases up the requirements a bit
14:33BrandonWbut the operations inside a commute transaction aren't ordered
14:33BrandonWor aren't *necessarily* ordered
14:34BrandonWbut then if the only thing that changes is the potential order of expressions in a transaction, how can that improve performance in commute vs alter?
14:34Chousukesay transaction A modified X with alter and Y with commute, and B modifies Y with commute; both start at the same time, but B finishes first; now, A doesn't need to restart.
14:34Chousukethat's as far as I understand it. I hope I'm getting it right. :/
14:35Chousukeof course, if A is designed so that it actually depends on the final value of Y, then it contains a bug :)
14:37BrandonWohhhhhhhhhhhhhh okay
14:37BrandonWthat just made it click
14:38BrandonWi'm was thinking of transactions as a single function call
14:38BrandonWbut you can have multiple alters/commutes at once
14:38zaphyrah. yeah. don't do that :)
14:38hiredmanBrandonW: right
14:38zaphyryeah, this is happening all at once, you really don't know what's coming in next
14:38Chousukethen there is ensure, which you need to use if you read Y and alter X based on the read value; if you just used deref, something else might use commute on Y and the altering of X would be done with an "old" value :/
14:38BrandonWnow i understand what the programming clojure book was saying when commute only requires the commut call to be re-executed, versus alter which needs to restart the entire transaction (which could contain a lot of other function calls)
14:39BrandonWensure hmm
14:40BrandonWi think that is going to be one of the difficulties after i finish the programming clojure book: finding out all the new additions since the book (or things the book didn't mention)
14:40Chousukeheh.
14:40Chousukeyou need to get chouser and fogus' book :P
14:40lypanovyeah, today.
14:41BrandonWis that the new one coming out soon?
14:41lypanovthey areon 37% discount.
14:41lypanovum. i'm a java / ruby head. alien to this strange () filled world.
14:41zaphyrhmm, yeah i read that- does that include dead tree versions when they're complete?
14:41lypanovany one think guice is needed if you have the various alt project abstractions lisp provides?
14:43BrandonWwhich book is written by chouser and fogus?
14:43lypanovBrandonW: http://www.manning.com/fogus/
14:43BrandonWi only see Practical Clojure by Luke Vanderhart in addition to programming clojure
14:43hiredmanlypanov: definitely not
14:43BrandonWawesome, i'll bookmark that for later
14:44lypanovand http://www.manning.com/rathore/ (which i have mainly as it looks neat to learn style from)
14:44lypanovhiredman: figured as much :)
14:44BrandonWclojure seems like it is speeding up
14:44lypanovand a good book on unit testing, universally applicable?
14:45lypanovs/lisp/clojure/
14:45zaphyrlypanov: i quite liked http://www.amazon.co.uk/Test-Driven-Acceptance-Java-Developers/dp/1932394850, ymmv
14:45RaynesIt's obvious that Joy is going to be awesome, but it's not complete enough for one to learn off of yet.
14:46BrandonW3 new books coming in the next 10 months
14:46BrandonWunit testing seems to lend itself to functional programming in general
14:47BrandonWokay i gotta go
14:47BrandonWthanks for all the help re: commute vs alter :)
14:48lypanovzaphyr: ah, koskela ... interesting: http://www.manning.com/koskela2/
14:49zaphyrhmm, looks like that one seems much more language agnostic
14:49lypanovreading through the chapter list makes me thing "oh, not needed with lisp" tbh
14:49lypanovs/thing/think/
14:50lypanovmaybe i'll just wait on the chapters in clojure in action for the moment
14:50lypanovpart ii has tdd stuff
14:50zaphyryeah, to a degree. the nice thing about test harnesses, primarily, is that when you want to change a big huge system, you can run all the tests to make sure you didn't break something far far away
14:51lypanovi'm already a tdd fan, just missing some of the tricks needed for java. but by the looks of it, half of the pain isn't even seen when using clojure.
14:52zaphyrahh, right, yeah. clojure makes a lot of the pain irrelevant
14:52Chousukeone tends to write a function and then test it immediately afterwards until it works :P
14:52lypanovChousuke: *nod*
14:52lypanovon that topic,
14:53lypanovdo you guys have tricks for printf debugging of complex things?
14:53lypanovinserting a print randomly in ruby is just trivial, but it gets quite complicated in clojure.
14:53hiredmandoto
14:53Chousukecomplicated? :/
14:53hiredmanand use prn
14:53hiredmannot println
14:54lypanovdoh! didn't know about prn. thx hiredman!
14:54hiredman,(doto 1 prn)
14:54clojurebot1
14:54clojurebot1
14:54lypanovi'm still half way through core. doing the projecteuler stuffs.
14:54ChousukeI suppose instead of random printfs you should use a proper logging macro so that they can be easily disabled when you don't want to see debugging output
14:54hiredmanChousuke: pfffft
14:55lypanovChousuke: its just for in repl debugging.
14:55hiredmanwhat are you? some kind of professional?
14:56lypanovooo. comp is neat.
14:57hiredmanI really should figure out logging, I did some on appengine, prn doesn't work there
14:59lypanovhiredman: ah, doto ... prn is cute. thank you. just what i needed.
15:03arohnerin clojure, strings are interned, so = compares by pointers, rather than strcmp, right?
15:04arohnerI'm wondering if I'll get in trouble by using strings as keys in a map
15:05Raynes,(keyword "hai")
15:05clojurebot:hai
15:05arohner,(keyword "I am a string with spaces")
15:05clojurebot:I am a string with spaces
15:05arohnershrug. that works too
15:06hiredmandon't do that
15:06hiredmanjust use strings
15:06Raynesarohner: I wasn't answering your question.
15:06Raynes:p
15:06RaynesI was just checking out the keyword function.
15:06RaynesUse strings.
15:07AWizzArdRaynes: I brought this issue up a few days ago.
15:07AWizzArd,{:a 1, :a 2}
15:07clojurebot{:a 1, :a 2}
15:07RaynesAWizzArd: I know.
15:07zaphyr?! how?
15:08Rayneszaphyr: Magic.
15:08zaphyrbroken magic XD
15:08RaynesIndeed.
15:08AWizzArd,(hash-map :a 1, :a 2)
15:08clojurebot{:a 2}
15:09billsmithaustin,(class {:a 1, :a 2})
15:10zaphyr:(
15:10zaphyr,(keys { :a 1 :a 2 :a 3 })
15:10clojurebot(:a :a :a)
15:11zaphyr,(conj { :a 1 :a 2 :a 3} { :a 4 })
15:11clojurebot{:a 4, :a 2, :a 3}
15:11zaphyr:S
15:13zaphyrIs it a bug in the reader? or nastier?
15:14hiredmanarraylist doesn't check keys
15:14hiredman~ticket #87
15:14clojurebot{:url http://tinyurl.com/y92lmv8, :summary "GC Issue 83: PersistentArrayMap trust the reader (map literals) too much", :status :test, :priority :low, :created-on "2009-06-17T20:36:09+00:00"}
15:14hiredmanthere is a patch :P
15:15zaphyraha. phew. i had a moment there. rhicky: accept this patch please :D
15:18hiredmanactually, the patch only adds guards to the reader, I suppose it should also add guards to arraymap
15:19zaphyrhmm. probably. how much of a hit is it?
15:19zaphyrperformance wise?
15:19zaphyr(correctness should probably be favored over performance here though, imo)
15:21hiredmanthe patch creates a hashset of the keys everytime a map literal is read
15:22zaphyryeah, one time reader costs probably don't hurt much at all
15:22hiredmanand it throws an exception if you try to read a map with duplicate keys
15:23zaphyr:)
16:10Scriptorhey everyone
16:23npoektopi still can't get parameters of a POST http method with compojure. Can anyone help me? http://pastebin.com/d6e4b5cd6
16:26hiredman"/:*"
16:26hiredmanif I recall
16:29zaphyrhmm. I have found myself wrapping awt with multimethods and macros. That isn't inherantly a bad thing is it? It makes things much more lispy :)
16:30hiredmanwhy are you using awt?
16:30zaphyrwell, the Graphics2D part of awt
16:30zaphyrswing for UI components, naturally
16:30hiredmanjust making sure
16:31zaphyrand you rightly should :)
16:31zaphyrthings like (with-graphics g (draw-line 50 50 200 200))
16:32zaphyrbinding g to a private fluid var *g*
16:34npoektophiredman: no, "/:*" doesn't work
17:22lypanovi don't get if-let...
17:23kotarak,(if-let [x 5] x 6)
17:23clojurebot5
17:23kotarak,(if-let [x nil] x 6)
17:23clojurebot6
17:23kotarak,(if-let [x false] x 6)
17:23clojurebot6
17:23kotarak,(if-let [x true] x 6)
17:23clojurebottrue
17:24lypanovi keep getting the equiv of "unable to resolve x in this context"
17:25kotaraklypanov: code?
17:25lypanovi'm too ashamed to paste :P
17:25AWizzArd;-)
17:25kotaraklypanov: you shouldn't be
17:26lypanovk... *shame*
17:26lypanovhttps://gist.github.com/c6791d30086488f4335c
17:26kotarakThe binding is only in the true branch of the if.
17:27lypanovline 19. has an if-let form. 'm getting the error: java.lang.Exception: Unable to resolve symbol: rest2-primes in this context (NO_SOURCE_FILE:385)
17:27lypanovah! doh
17:27kotarakAfter the seq call you know it's nil.
17:27kotarakin the else branch, that is
17:27lypanovgood point... how on earth did this code work.
17:28lypanovthinking in clojure is teh hard
17:28kotarak*shrug* Schroedingbug
17:28lypanovit wasn't used anyway, so the nil just got ignored previously
17:29kotaraklypanov: no, it's not. Clojure is veeery consistent. cf. alter, commute, swap!, update-in, .... Know one, you know the others.
17:29lypanovthank you :)
17:29lypanovkotarak: agreed, but when you're 3 days in... and you're trying to solve problems that you'd find hard in any lang. its teh hard. :P
17:29kotarakok. That's true. :)
17:37AWizzArdlypanov: already some hours ago i saw you talking.. were you learning all those hours Clojure?
17:38lypanovAWizzArd: and watching crap tv :P
17:38lypanovbut yeah, crap tv takes around 5% in my brain-top
17:39AWizzArdmaybe resting can be nice from time to time :)
17:39lypanovAWizzArd: my wife will force me to do that eventually.
17:39lypanov:P
17:39AWizzArdgreat
17:39lypanovanyway. inbetween coding i'm watching the "clojure for lisp programmers" video at double speed.
17:40AWizzArdyes
17:40lypanovokay. getting closer to not sucking: https://gist.github.com/c6791d30086488f4335c
17:48MecIn emacs, is there a way to get things to output to the repl instead of *inferior-lisp* or *slime-events*?
17:49the-kennyMec: I think there was some variable in emacs to accomplish that
17:53the-kennyha!
17:53AWizzArdJa?
17:53the-kennyMec: Try C-h f slime-redirect-inferior-output
17:54arohnerI have a list, I want to map over it, but I want each call to give me two adjacent elements. Is there a function that does that?
17:55arohneri.e. (map* f (range 5)) would call (f 0 1) (f 1 2) (f 2 3) ...
17:55the-kennyarohner: destructuring and (partition)
17:55zaphyr,(partition 2 1 [1 2 3 4 5 6])
17:55clojurebot((1 2) (2 3) (3 4) (4 5) (5 6))
17:55the-kenny,(doc partition)
17:55clojurebot"([n coll] [n step coll] [n step pad coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap. If a pad collection is supplied, use its elements as necessary to complete last partition upto n items. In case there are not enough padding elements, return a partition with less than n items."
17:55arohnerthanks!
17:59Mecthe-kenny: thanks, that's exactly what I wanted
18:02lypanovok.
18:02the-kennyMec: You're welcome :)
18:02lypanovcan anyone with a few minutes go over https://gist.github.com/c6791d30086488f4335c and tell me why it sucks?
18:03lypanov(other than the fact that lcm can be done way way easier ;) )
18:03Mechmm that didnt redirect all, is there a way to redirect output from evaluating an expression to the repl instead of just the little line at the bottom?
18:04kotaraklypanov: something more general: use (next ...) instead of (seq (rest ...))
18:06lypanovcute. thank you.
18:08zaphyri need to dispatch on my defstructs and general classes- am i doing this right? http://paste.lisp.org/display/94500
18:10MecI think you can replace tag-or-class with just type
18:10zaphyraha, thanks :)
18:10Mecmaybe not
18:11zaphyrnope. PersistantStructMap :)
18:13lypanovis there any other way to do multi return value than destructuring in the caller?
18:13technomancylypanov: how else would you?
18:13technomancyto return multiple values, you'd have to return a collection type
18:14lypanovclomagic? :P no idea.
18:14zaphyrtchnomancy: call-with-values (scheme) multiple-value-let (common lisp)
18:14zaphyrbut clojure doesn't support that behaviour
18:14technomancyzaphyr: what does that mean?
18:15the-kennylypanov: It's easy to implement with metadata, but they're bound to types which support metadata then
18:15technomancyI mean, if multiple values are returned, it must be a collection type, right?
18:15zaphyryou cease to have functions that return
18:15the-kennytechnomancy: Common Lisp has "Optional Return Values". There's one main-value and optional, additional values which you can access with multiple-value-bind
18:16zaphyrahh, multiple-value-bind, i thought that was wrong =]
18:16lypanovnow i understand why clojure is a good lang for me to learn ;)
18:16lypanovlast time i started cl i almost fainted.
18:16zaphyrtechnomancy, effectively (inside the compiler) a function calls another function with the arguments returned by values
18:17technomancyand that's considered useful?
18:17zaphyrthe net result is you don't end up boxing up anything to get multiple returns
18:17the-kennytechnomancy: It's useful.
18:17the-kennyIt's possible if the value returned by let is nil or it wasn't found, without a special value for "not found"
18:18lypanovokay. taking AWizzArd's advice and taking a much needed sake drinking break.
18:18technomancyso it reduces the need for things like containts?
18:18technomancy*contains?
18:19zaphyrand partition can just return two values, rather than a list of two values
18:36zaphyrclojure.lang.PersistentBitVector. want!
18:37hiredmandamn
18:37hiredman(+ 1 2) in the repl doesn't call Expr.parse
18:37clojurebot3
18:37hiredmanclojurebot: byte me
18:37clojurebotMy mother? I'll tell you about my mother
18:42hiredmanI'm thinking #^{:primitive true} (+ (float 1) (float 2)) is nicer than (jop + (float 1) (float 2))
18:44zaphyrcould there not be f+ f- f* ... i+ i- i* with automatic coercions?
18:45hiredmaneasier to dispatch (and better) to dispatch on type
18:45hiredmaneasier (and better) to dispatch on type
18:46zaphyrhmm, yeah i suppose so. maybe just add a float reader format #^{:primitive true} (+ 1.0f 2.0f)
18:47hiredmanzaphyr: but then what about non-literals?
18:47zaphyruse float still :)
18:47zaphyri'm just thinking about populating a matrix full of float literals. ick.
18:47hiredmananyway, in my conception this is not for users
18:48hiredmanthis is at the bottom of the numbers dispatch stuff that has already determined the types of all the numbers
18:48zaphyrah, right
18:58gstrattonHi, I can't figure out why this doesn't work: (for [i (map vector '(float int int) '(0.5 2 4))] (apply (first i) (rest i)))
18:58gstrattonI want to apply a list of args to a list of single-valued functions
18:59gstrattonI'm sure there are multiple shorter ways which do work, but I'm stumped finding them
18:59hiredmanthat is a pointless thing to do
19:00hiredmanyou are casting to primives, and then sticking the result into a collection that does not support primitives
19:00hiredmanso they are boxed all over
19:05zaphyrgstratton: to make the code work, you might want to try [float int int] instead of '(float int int)
19:06zaphyrbut as hiredman says, you'll be casting to integers and wrapping them back into boxed Integers, so its probably not the best thing to do
19:07gstrattonOkay, thanks, I'm reading up on boxing now.
19:08zaphyri'm not sure what the effect of calling a symbol as a function is, but that's what you were doing
19:09gstrattonzaphyr: Oh, I see, thanks
19:09zaphyr,('foobar 3)
19:09clojurebotnil
19:09hiredman,('f {'f 1})
19:09clojurebot1
19:10zaphyrahhh, so like keywords
19:10zaphyrthanks :)
19:10hiredmanyes
19:46zaphyrhmm, if i implement a version of drop-while which works from the end for vectors, would that still be horrible?
19:47zaphyri think that removing from the end of a vector via subvec would be O(1), so it would be fine?
19:59wilighttps://gist.github.com/2574d3bba9a9540c1bb8 My first attempt at validation. Constructive criticism would be most welcome.
20:03hiredman:D
20:04wiligheh
20:04zaphyryou could filter with identity instead of #(not (nil? %))
20:05hiredmanwilig: if you collapse each verification function into a single function, you can use a map instead of a vector of vectors
20:05hiredmanbut I guess that has downsides as well
20:06hiredmanI have #^{:primitive true} (+ (double 1) (double 2)) compiling to a dadd :D
20:06zaphyr\o/
20:08wiligI'm so far over my head. Haven't even made it to the macro chapter in programming clojure yet. Having lots of fun though.
20:09wiligzaphyr: Could you use little words and explain filter with identity?
20:09zaphyr,(filter identity [1 2 nil 3 4])
20:09clojurebot(1 2 3 4)
20:09wiligAh!
20:09zaphyr,(doc identity)
20:09clojurebot"([x]); Returns its argument."
20:10wiligOh, thanks for showing me the light. Much better.
20:10zaphyrnp
20:12qedwilig: ive been at clojure for a few months and i still feel the same way, learning so much fun stuff along the way though
20:12qedclojure is like a supplementary CS education
20:12wiligI totally agree
20:13wiligI've always wanted to learn a bit of lisp, and I'm having the time of my life.
20:14wiligHardest part is internalizing how much can be accomplished just by combining the core functions in various ways.
20:16hiredmanuser=> (expression-info (with-meta '(bit-shift-right (byte 10) (byte 1)) {:primitive true}))
20:16hiredman{:class byte, :primitive? true}
20:16zaphyr:D
20:16zaphyrmuch win
20:17hiredmanwell, I still need to see if rich is interested in it
20:18qedwilig: i like to look at code ive written in other languages and adapt it to clojure -- it helps my brain a bit to see what i used to think of, and how to think of it in clojure
20:19zaphyrhiredman: is it generating java bytecodes, or calling static methods that do the work?
20:21wiligqed: actually that's a very good idea. I may have to try that. thanks.
20:22hiredmanzaphyr: java bytecode
20:22hiredmanright now + and similar compile down to calls of static methods from Numbers.java
20:22zaphyrthen I totally have a use for that. can't wait to play with it :)
20:23hiredmanbut this le you generate bytecode directly, trading off flexibility
20:23hiredmanlets
20:24zaphyrwould be incredibly useful for DSLs I'd wager
20:24hiredmanhow do you figure?
20:24hiredmanDSLs usually seem to want more abstractions and indirection, not less
20:25zaphyryeah, but say your language works only with ints and longs
20:25zaphyrand needs to go faster than unboxing into bigints
20:26zaphyrit looks like you could create a mini compiler for said language with that, if i understand you correctly
20:26zaphyr(potentially without requiring a clojure runtime)
20:26hiredmanif you want to write a compiler you can use the asm library, just like clojure does
20:27zaphyrhmm. good point.
20:34zaphyrhiredman: but it might make this less painful, right? http://paste.lisp.org/display/94503
20:37hiredmanI don't know
20:45hiredmanhttp://gist.github.com/297122
20:46zaphyrinstruction 12 \o/ :)
20:46zaphyri presume you only box everything back up at the very end
20:47zaphyrso there could be much hair in that function
20:47hiredmanthe compiler infrastructure takes care of that
20:47hiredmanit's pretty nice, .emit vs. .emitUnboxed
20:48zaphyri like it
20:48hiredmanin this case .emit calls .emitUnboxed and then does the boxing stuff
20:49zaphyryeah. literally my only gripes are lack of primitive types in arguments/return, and inability to also inline that (for extreme performance win). copy-in-place optimization would probably make my vector math library faster than the java version...
20:50hiredmanit's neat to see the locals clearing stuff aconst_null, astore_1
20:50hiredman,(doc definline)
20:50clojurebot"([name & decl]); Experimental - like defmacro, except defines a named function whose body is the expansion, calls to which may be expanded inline as if it were a macro. Cannot be used with variadic (&) args."
20:51hiredmanI now rhickey is thinking/working on a primitive argument interface to fns
20:51zaphyryeah, but i want an inline metadata to stuff on standard fns
20:52zaphyralthough, definline does do the trick for now
20:52zaphyrjust means i have lots more #'s in my code than i'd like
20:53hiredmanclojurebot: performance
20:53clojurebothttp://clojure.org/java_interop#toc46
20:57zaphyryeah. actually it was unclear, do i need (int ...) around Float/floatToIntBits, given that that returns an int anyway? I'd imagine not
20:58hiredmanI don't think so
20:59zaphyrfigures. that and a bunch of vector math stuff was the first thing i wrote in clojure, and already it looks silly
21:00MecIn emacs, is there a way to redirect the output from lisp-eval-last-sexp to the repl instead of *messages*?
21:16Lewishamhi all, can anyone figure out how I would get this function to work? recur isn't the tail expression, but I can't seem to work out how to get it to be the last expression... http://pastie.org/812951
21:22somniumLewisham: try writing it with reduce
21:22Mec(reduce + (map count-words lines))
21:23Lewishamah, I thought about that, but what I actually return is a map of the words and their occurance, such as {"Me" 1, "You" 2}
21:23Lewishamthat's why I was using merge-with
21:24Lewishamso it keeps merging the maps until you get one final big one
21:24Lewishambut it (understandably) barfs on a file of any large size
21:24Lewishamwith a StackOverflowError
21:24hiredmanuse reduce
21:25Mecso count-words returns a map?
21:25LewishamMec: yes :)
21:26Lewisham(reduce (merge-with +) (map count-words lines)) ?
21:26hiredmanyou need to use partial
21:26Lewishamthat NPEs in my code, but that's not to say it's because my count-words function is bad
21:26hiredman,(merge-with +)
21:26clojurebotnil
21:26hiredman^
21:27hiredman,(reduce nil '(1 2))
21:27clojurebotjava.lang.NullPointerException
21:27hiredman^-
21:27Lewishamah
22:04technomancyjust in case anyone's not following the mailing list, there's a Seattle Clojure meeting next thursday: http://bit.ly/d1rwpe
22:07Lewishamhiredman: Mec: somnium: I got it working, thank you :) Just have to hope I get my RAM back at some point :)
23:16ag90Hey I have a question. I'm working on this code and for the past few hours I was stuck on this small function. After many random printlns I concluded that it got stuck when it called a particular function. No errors. It just didn't work. When I tried that function in REPL, I got a simple error about trying to use a reference as a sequence. Worked perfectly after dereferencing. How can I enable such error messages outside the REPL?
23:16ag90TL;DR - I want to know if there's a way for Clojure to raise errors outside the REPL when running as a script?
23:16technomancyag90: the main difference between the repl and stuff inside a script is that the repl prints everything, which forces lazy sequences to be evaluated
23:17technomancyyou can wrap a lazy sequence in "dorun" or "doall" to force it in any context
23:17ag90Oh. So this problem was because of laziness?
23:17ag90(the missing error messages)
23:17technomancy90% sure it is
23:18technomancythat's by far the most common cause of "works one way in the repl; another way in a script" problems
23:18ag90Oh. Great! Thanks.
23:19technomancyuse dorun if you need return values; use doall if you just want to force the seq
23:19technomancyor possibly replace for/map with doseq; depends on the context
23:27tomojlancepantz: did you figure out the body thing with compojure?
23:27tomojI just needed to do that as well
23:27tomojI found a function in compojure called slurp-body which slurps the body into a string, but it's private
23:27tomojso just ended up wrapping PushbackReader and InputStreamReader to hand to c.c.json.reda
23:27tomojs/reda/read/
23:28tomojdid it in middleware so in a handler (:json request) is the parsed json body
23:28hiredmanthat is a nifty idea
23:30tomojit gave me an "I love clojure" moment
23:30tomoj:)
23:32piccolinoHow would one check if a particular object is an instance of an array of bytes? I'm having trouble with isa? and instance?, neither seems to work with bytes as a parameter.
23:32tomojhmm.. I feel like I also could use a macro over let which lets you bind names to values in maps in the request map, to replace (let [foo (-> request :bar :foo) bizz (-> request :baz :bizz)] ..)
23:34tomoj,(instance? (Class/forName "[B") (byte-array 10)))
23:34clojurebottrue
23:34tomojwonder if there is a prettier way to get (Class/forName "[B") ...
23:34piccolinoAh, OK, thanks.
23:34hiredmantomoj: not really
23:35hiredmanfor type hinting there is ^bytes
23:35hiredman#^bytes