#clojure logs

2008-12-22

00:03hiredmanthe hard drive in the machine that was running clojurebot died
00:24Chouserhiredman: :-(
00:25hiredmanit maybe a week or two before it gets rebuilt
00:50joha1would like to get unbuffered console input (e.g. pressing a key should return at once, instead of waiting for ENTER), preferably without having to use something big like JCurses. So far I'm failing. Any ideas?
00:56Chouserjoha1: in C you'd use tcsetattr to set the terminal's parameters
00:58joha1yes, I tried something similar with stty (I'm on Linux). Didn't work, but perhaps my mistake
00:59Chouserah, shelling out to stty?
00:59Chouserthat rings a bell...
00:59joha1well, I couldn't make it work, but perhaps you have seen something similar?
01:00Chousernot from java/clojure, but I'm pretty sure I've done it. maybe from perl?
01:00joha1Hmm, perhaps I should google a bit more. I already tried "stty -icanon min 1"
01:05Chousertry adding "time 0" to that
01:11ChouserI don't think that's it.
01:12Chouseryou're using Runtime's .exec method?
01:19joha1chouser: yes i am
01:19joha1must be a better way
01:19Chouserok, the problem is that the sub-process is run in a way that's not associated with the terminal
01:20joha1makes sense
01:20Chouserif I add -F /dev/pts/termnum to the stty command line, it works
01:20Chouserso, what to use for termnum?
01:20ChouserI tested by running "tty" on the command line and copying the result into my test program manually.
01:21Chouserbut I don't know if there's anyway to get the terminal associated with the java process's stdin
01:22joha1running tty from Runtime.exec would give the tty for the new process instead, right?
01:22Chouserright.
01:22Chousertrying that got me back the string "not a tty"
01:23joha1in worst case I could always to to get JCurses to work. Much overhead for something so simple, though...
01:24joha1thanks anyway
01:24Chouseror use Swing. :-)
01:24joha1sure, but sometimes you just need a text console
01:24joha1:)
01:24ChouserI think you mean a JTextPane
01:24Chousersometimes you just need a JTextPane
01:25joha1not if I don't have X on my server
01:26zakwilsonPeople have X on servers?
01:29Chouserjoha1: you could do the stty setup/teardown in a launching script
01:31joha1I've just found a page describing how to set up nonblocking input in Java using the stty method
01:31joha1http://www.darkcoding.net/software/non-blocking-console-io-is-not-possible/
01:31joha1will try to get this working in clojure
01:32joha1but of course I could set it up in a calling script as well
01:36Chouserhuh, he bounces it through "sh -c ... < /dev/tty" and apparently that does it.
01:39Chouseroh, nope, I screwed up my test.
01:47joha1Yeah, this works!
01:47joha1 (import '(jline ConsoleReader))
01:47joha1(.readVirtualKey (new ConsoleReader))
01:47joha1and there are lots of other useful functions in Jline
01:47Chouser:-)
01:58lisppaste8Chouser pasted "unbuffered input at text terminal" at http://paste.lisp.org/display/72515
01:59joha1nice
02:00Chouserbut if jline of jcurses is an option, I'm sure you'll have better results there.
02:01joha1it will certainly be easier, and multi-platform. Still interesting to know that it can be done
04:10klinkershow fast is Clojure?
04:10klinkersbenchmarks?
04:14leafwklinkers: as fast as java.
04:15leafwbut, considering it enables better algorithms, your programs may be faster than naive, imperative implementations in java.
04:18klinkersenables bette ralgorithms?
04:18klinkersdont yu always have more options in java? you can do inplce sorting etc
04:18klinkersormaybe you cna in clojrue too
04:19klinkersanyway does AOT mean I can compile to a JAR? and that other java-libs can use my clojure code?
04:19leafwyes.
04:26lisppaste8leafw pasted "benchmark" at http://paste.lisp.org/display/72517
04:26leafwklinkers: have a look for yourself.
04:26leafwit's a very simple benchmark, adding numbers.
04:34klinkersjanino?
04:35klinkersclojure wih primitives is that doing things like : (+ (int 5) (int 6)) ?
04:37leafwand type declarations.
04:44klinkersthat is a type declaration no?
04:49leafwwell, (int 5) is a type declaration indeed, although I can't help thinking of it as a cast (but it isn't)
04:50leafwalthough (int 1.5) prints 1.
04:50leafw"Coerce to int", (doc int) says.
05:00klinkersclojure.examples.hello
05:00klinkersis clojure and examples directories then?
05:01hoeckklinkers: right
05:02hoeck./clojure/examples/hello.clj
05:05klinkershmm i use september there fore compiel is not working?
05:06leafwklinkers: pull svn
05:08hoeckklinkers: or use the clojure pre realease
05:08hoeck(the download link on clojure.org)
06:18bOR_Hi all, I ran into: java.lang.Exception: Transaction failed after reaching retry limit (NO_SOURCE_FILE:0)
06:18bOR_and on the forum I see that stuart sierra ran into the same thing, and rich recommended not using a wait function.
06:19bOR_wondered if the official (await ... ... ..) is also a dont-use-this-in-very-long-loops wait function
06:19bOR_http://groups.google.com/group/clojure/browse_thread/thread/c8c3510f01f951e1/a2b74c4fd85c89bb?lnk=gst&amp;q=retry+limit#a2b74c4fd85c89bb
06:22bOR_it seems that all elements in my vector of refs are locked now.
06:22bOR_mm.
06:23fyuryubOR_: I can't really answer your question, never encountered the problem so far, but try asking in a couple of hours (5-6)
06:23fyuryubOR_: and a source snippet would help
06:23bOR_I'll drop it into the forum then.
06:26fyuryutry structuring the code differently, waiting in a loop doesn't seem like a goo idea (but without knowing what you want to do exactly, it's hard to tell)
06:26fyuryumaybe agents would be a good fit for you task?
06:29fyuryubOR_: oh wait, you're using await in that loop?
06:35jgracinreplaca: fantastic job on cl-format! I was hoping someone would do it eventually, and this was quick.
06:43bOR_(sorry, was cleaning my bike). I've 8 agents that each are send off in a loop, at the end of sending them off, I await them all.
06:43bOR_the loop itself is a million times.
06:43bOR_(but I'm not sending off 8 million agents at the same time)
06:43bOR_(just 8)
06:44bOR_each agent has the task of doing 7 things to every reference in a vector, in random order.
06:44bOR_and right now, while we're no longer in a loop or anything,
06:45bOR_I can't even do a single thing to a single ref anymore without it failing due to many retries.
06:45bOR_is there any way to see which refs are all locked right now, and by whom they are locked?
06:54fyuryuand how big is the vector that the agents operate on?
06:55bOR_vector of 1000 refs
06:56bOR_it's an agent-based model. each ref might contain a host, and the 7 things I'm doing to them are birth / death / evolution / infection.
06:57bOR_thanks for talking though, will help in knowing what information to put in the google group post.
06:58fyuryubOR_: I don't think there is a way to see who locks the refs in a given moment
06:59bOR_think I know..
06:59bOR_based on doc await.
06:59bOR_if there's one of the transactions not returning.
06:59bOR_await just keeps blocking everything, I guess.
07:00fyuryuah, so you're not sure if every agent completes his work?
07:00bOR_as await might still be waiting for one of the (send-off) to finish.
07:00bOR_normally it should.
07:00bOR_and it tends to
07:01bOR_but maybe if for some reason I don't know yet, one of the send-off agents blocks.
07:01bOR_ok..
07:01bOR_that's a good question.
07:01bOR_what happens with await, when one of your threads runs into the retry limit.
07:02fyuryu(doc await-for)
07:02bOR_gracias. that might work indeed.
07:02bOR_normally, a single year takes about 60 seconds to compute.
07:03bOR_well, sometimes 90
07:03bOR_so I can just put the await on 3 minutes.
07:04bOR_I'll make a post, cause I wonder what happens with the thread that didn't return on await.
07:24klinkersim trying to compile but the examples are not so easy
07:24klinkersok i have a file C:/clojure/progs/hello.clj
07:24klinkershow would I compile it?
07:24klinkershte namespeace should contain :gen-class?
07:24klinkersand the compeltr apth?
07:25leafwklinkers: http://pacific.mpi-cbg.de/wiki/index.php/Clojure_Scripting#Generating_java_classes_in_.class_files_from_clojure_code
07:26leafwklinkers: http://clojure.org/compilation
07:49klinkersyes but what im wondering voer is namespaces
07:50klinkersif i ahve a file
07:50klinkersC:/clojure/progs/hello.clj
07:50klinkerswhat namespace should i put it in?
07:51Chouserklinkers: they only way for that path to be a valid lib would be if it has the namespace progs.hello (and C:/clojure is in your classpath) or the namespace clojure.progs.hello (with C:/ in your classpath)
07:54klinkersi have C:/clojure in my classpath and I have the file int he namespace progs.hello
07:55klinkersi do (compile 'progs.hello) and i get:
07:55klinkersjava.io.IOException: The system cannot find the path specified (hello.clj:1)
07:55klinkersuser=>
08:00fyuryuklinkers: "progs.hello" namespace == "c:/some-path/progs/hello.clj", and c:/some-path AND c:/some-path/classes must be in your classpath.
08:04klinkersjava.io.IOException: The system cannot find the path specified (hello.clj:1)
08:04klinkersprogs.hello=>
08:04klinkerswhat is classes there btw?
08:04klinkersthe classes it uses u mean?
08:05Chousukeklinkers: the classes dir contains the compiled code
08:05Chousukeor will contain
08:05Chousukeit needs to exist and be in the classpath before compilation though.
08:05klinkershttp://hpaste.org/13252
08:06Chousukewhich I think is not very nice, but I don't know a way around it either.
08:06klinkersshould it be called classes?
08:07Chousukeklinkers: you don't need str with println btw.
08:07Chousukeit can take multiple arguments.
08:07acieroidhow can I cast an Integer to a Char with clojure ?
08:07klinkersstill: progs.hello=> java.io.IOException: The system cannot find the path specified (hello.clj:1)
08:08Chousukeyou'll want your classpath to contain C:/clojure/;C:/clojure/classes/
08:09Chousukealong with the others
08:09Chousukeand remove the entry with hello.clj in it
08:09koguacieriod: char?
08:09acieroidhum
08:09acieroidforgot this function ><
08:09Chousukeklinkers: and make sure C:/clojure/classes/ exists
08:10koguok, im really new to lisp, can someone help me with this really basic thing?
08:10koguhttp://hpaste.org/13253
08:11koguit always prints 0
08:11klinkersyou should use if
08:11klinkersinstead of when
08:11klinkersi think
08:11acieroidno
08:11Chousukeno
08:11acieroidbecause data are immutables
08:11klinkersyes and branch
08:11Chousukekogu: + does not change points
08:12klinkersah ysw recur points
08:12Chousukekogu: it only outputs a new value, which is promptly discarded
08:12kogui see, so how can i use a global variable for points?
08:12acieroidwith refs
08:12rhickeycould everyone please use paste.lisp.org please? then we get a single archive to look back through
08:13rhickeylisppaste8: url
08:13lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
08:13Chousukekogu: once you (let [points 0]) points is 0 and will not change
08:13koguok, so how do i define a variable which will change
08:13Chousukekogu: for that code, you don't.
08:14Chousukekogu: simply modify the logic to call recur in a way that passes the change to the next loop :)
08:14koguah i see, that makes sense, thanks a bunch, emacs you bastard, here i come
08:14Chousukebut if you really need a global "points" state, the way to do that is to use a ref and dosync
08:15kogui haven't gotten to that part yet, but i will keep that in mind
08:15Chousukebut surprisingly many apps don't even need refs
08:16Chousukeyou can also have state as something that is passed to each function and they then return a new state
08:18koguhmmmm
08:18koguhave to grok it, still think in java
08:18koguone more ques, how can i do a lot of if elseif elseif else?
08:19Chousukecond
08:19koguwow, thats right
08:19koguty again
08:21Chousukeusing (or) can also be useful if you need to stop as soon as you get something non-false
08:23Chousukeor returns the first non-false value as is, so the following will work assuming the search function returns nil if an item is not found: (defn get-item [] (or (search source1) (search source2) :default-item))
08:24klinkersacieroid: Integer.
08:25acieroidklinkers, char works perfect
08:27klinkersand it should be c:/clojure/classes/ not c:/clojure/progs/classes or anything?
08:27klinkersprogs.hello=> (apply char "2")
08:27klinkers\2
08:27klinkersprogs.hello=> (Integer. "2")
08:27klinkers2
08:29Chousukeklinkers: yeah, c:/clojure/classes/
08:31klinkersso what could i be missing?
08:31klinkersjava.io.IOException: The system cannot find the path specified (hello.clj:1)
08:31klinkersi ahve the correct paths in the classpath
08:32klinkerspath specified (hello.clj
08:32klinkersshould that says the whole pth to hello.clj?
08:32Chousukeno.
08:33Chousukedoes the classes dir exist?
08:33Chousukeit must exist when you start the VM
08:33hoeckklinkers: have you set *compile-path* to "c:\\clojure\\classes" ?
08:34Chousukeshouldn't that be the default.
08:34klinkersoh
08:34klinkerswhere is compile-path?
08:34klinkerswhere do is et it anyway?
08:34Chousukein your clojure program
08:34hoeckit defaults to "classes"
08:35Chousukea simple (set! *compile-path* "c:/clojure/classes") at the top of your script should do I guess.
08:35klinkersset! ?
08:36hoeckor do (binding [*compile-path* "bla\\foo"] (compile 'clojure.expamples.hello))
08:36klinkersu emand ef?
08:37hoeck*compile-path* is bound above the repl so you can set! it
08:37klinkersim using emacslisp in clojure then?
08:37Chousukeno.
08:37Chousuke*compile-path* is a clojure setting, not an emacs one
08:38klinkershello mama!
08:38klinkersthere it worked
08:38klinkersit egenrates a bunch of .class stuff
08:39klinkersthen i can compile that to a JAR with javac!?
08:39ChouserI use the 'jar' command to produce a .jar file
08:42klinkersexactly how? you mvoe to ~/classes/ and then?
08:43klinkersor jsut form anywhere(mind me i dont know java tow ell)
08:43koguklinkers: you just zip that folder, and rename it's extension to .jar
08:44koguklinkers: make sure that the folder path is preserved
08:47Chouserkogu/hoek: you can set up the manifest correctly like that?
08:48kogucho: usually if you don't have a main class, you don't need the manufest file
08:48Chouserah, ok.
08:49klinkersjars a re zipped .class-collections?
08:49Chouserklinkers: yes
08:49Chouserwith some (apparently optional) extra header info
08:50kogujars, wars, *ars
08:50koguall the same
08:50klinkersso i should have another word between progs and the actual program then
08:54lisppaste8kogu pasted "untitled" at http://paste.lisp.org/display/72523
08:54koguummm, how to i return the points from that function?
08:55Chousukekogu: use let instead of def
08:55Chousukekogu: and: (do (println points) points)
08:55klinkerskogu: exactly what are yout rying to do? idiomatically you shouldnt use de flike that
08:55Chousukeprint*
08:56kogucho: print is just for debugging
08:56kogucho: im loopping 10 times, creating a new roll each time, eval the roll and adding points accordingly
08:57Chousukekogu: oh right.
08:57Chousukekogu: I misread that thing :P
08:57Chousukeuse if instead of when then
08:57Chouserchange your (when (> counter 0) ...) to (if (zero? counter) points (do ...))
08:58kogucho: ah i see, ty, so i change def -> let, and change when->if
08:58kogucho: ty
08:58Chouserright -- those changes are related, but you need both.
08:58Chouserthose changes are NOT related, but you need both
08:59kogucho: right, let because i want it scoped locally, and if to return the points
08:59Chouserright
08:59Chousukekogu: (if (> counter 0) (let [roll (new-roll)] (print points) (recur (dec counter) (+ points (eval-roll roll)))) points)
08:59Chousukeparentheses may not match...
08:59Chouserwell, also 'let' because 'def' inside a function like that is icky.
09:00hoeckkogu: or do (reduce + (take 10 (repeatedly new-roll)))
09:04Chousukeor because you need eval-roll: (reduce + (take 10 (repeatedly #(eval-roll (new-roll)))))
09:05kogucho: whoa!!!
09:05kogulet me try that
09:14kogucho: dude! that was awesome, that worked like a charm
09:17Chousukeit was hoeck's idea though. I just fixed it to match your code. :)
09:18Chousukeoften you can use the higher-order functions and reduce instead of explicit loops.
09:19kogucho: well i got both working, i need to look into this reduce, never used this before
09:23Chousukekogu: reduce is a function which takes a function of (at least) two arguments and a sequence, then applies that function to the first two values of the seq, then again to the result and the next value in the seq, etc.
09:24koguhmmm, never thought it could be used like this
09:24Chousukeso (reduce + [1 2 3 4]) = (+ 4 (+ 3 (+ 1 2)))
09:24kogubtw, anyone using clojure-mode on emacs here? how to see which parens does the parens under the cursor match to?
09:24hoeckkogu: i recommend the http://clojure.org/sequences page for an overview over the sequence library, though you may just use (doc reduce) at the repl
09:25koguwill read it, right now
09:25Chousukebut of course works with any function
09:25Chousukefor example, to find the max value of a sequence: (reduce #(if (< %1 %2) %2 %1)) []
09:26Chousukeoopw
09:26Chousukewell something like that
09:26jdzkogu: that's an emacs configuration option, "paren match highlighting" in options menu
09:26Chousukedoes anyone know how to make emacs emit only spaces instead of tabs?
09:26ChousukeI noticed mine emits tabs and that screw up formatting sometimes.
09:27jdzChousuke: indent-tabs-mode
09:27jdz(set it to nil ;)
09:27hoeck(setq-default indent-tabs-mode nil)
09:27hoeckbut mine is an xemacs
09:27jdzyes, M-x customize-variable intent-tabs-mode
09:29Chousukethe customisation facilities in emacs are awesome
09:30Chousukemaybe a bit too awesome
09:30Chousukethere's so much to customise it can be difficult to find the relevant stuff
09:31hoeckbut you can do <tab> and look at the autocomplete buffer
09:32hoecki whish i could do this in the crappy powerbuilder ide i have to use at work :(
09:36klinkersnice
09:36bOR_Hi rhickey, working on a reproducable version that doesn't take 3 hours on 8 cores :)
09:37bOR_posted the source online.
09:38klinkerswhen will v1.0 of clojure come out?
09:38bOR_as long as none of you here are in the competitive field of doomsaying, I shouldn't get into trouble of sharing it here.
09:40hoeckklinkers: http://groups.google.com/group/clojure/browse_thread/thread/381e575bad1cfb77
10:00rhickeybOR_: I put up a rev that might help your problem - I think once you started failing you might have quickly wrapped the timestamp - now an AtomicLong in svn 1181
10:01bOR_thanks.
10:01bOR_not sure I understand.
10:01bOR_what you mean with wrapped the timestamp / now an AtomicLong.
10:02kogurhickey : thank you for clojure
10:02rhickeybOR_: was an AtomicInteger - but once you started failing and let the sim continue you'd consume timestamps at a high rate
10:02rhickeykogu: you're welcome!
10:02bOR_ok.
10:03bOR_the high rate was 1.8 seconds? ("Elapsed time: 1871.911 msecs" )
10:05rhickeybOR_: that would explain your locked up situation afterwards, but you probably still have some bad transaction granularity.
10:06bOR_hehe. getting something to run concurrent in clojure is easier than understanding all the things that go wrong. Reading up on transaction granularity now. I'll just see if I can make a version of the model that quickly produces the error.
10:09bOR_I'll see if I can reduce it somehow.
10:11bOR_from birth: (let [living (apply vector (gather :born))
10:11bOR_ah.
10:11rhickeyright
10:11bOR_birth is doing a gather of all living.
10:11bOR_and gather will be locking the whole thing.
10:11rhickeythat's the gather I saw
10:11bOR_the rest almost only messes with a single ref.
10:12rhickeybOR_: it won't be locking, as it is only a read, but it will increase the footprint of the world snapshot required for that dosync
10:13bOR_ah.
10:14bOR_but if that is just a memory thing, I seem to have enough memory.
10:14bOR_for a moment thought it would be locking, but it is indeed only reading, and using a snapshot of what once was a father ;)
10:16bOR_at most I'm doing 8 births at the same time in the whole population. that doesn't seem too bad.
10:16bOR_(8 processors)
10:27klinkershow can i remove a namespace from the repl?
10:28hoeck(doc remove-ns)
10:28klinkersand how do I require my user-file? do i have to put it in a namespace?
10:29klinkersbut the repl still says the old namespace...
10:35koguwhat's the opp of "nil?"
10:37Chouserkogu: depends, but generally 'seq' or just the object itself
10:37Chousers/generally/usually/
10:39kogucho: its a number, hmmm
10:39kogu(defn eval-roll [roll]
10:39kogu (let [payout (odds roll)]
10:39kogu (if (nil? payout) -1 (- payout 1)))
10:39koguwhere "odds" is a map
10:39Chouseryou want to know if the map is empty?
10:40Chousukepayout is a number?
10:40koguno, if i don't know have the key in the "odds" map, i get back null, which throws nullpointer
10:40koguin if(payout)
10:40Chousukekogu: you could use (get odds roll 0)
10:40Chousukefor a default value
10:40Chouserright, or just (odds roll 0)
10:43kogu(defn eval-roll [roll]
10:43kogu (let [payout (odds roll 0)]
10:43kogu (if (payout) -1 (- payout 1))))
10:43Chouserno
10:43Chouser(defn eval-roll [roll] (- (odds roll 0) 1))
10:44koguyeah, that makes more sense
10:44koguty again
10:44Chouserbut in the general case of wanting to handle a failed lookup separately, by default map lookups return 'nil', which in an 'if' means the same as false.
10:45Chouserso: (let [payout (odds roll)] (if payout (- payout 1) -1))
10:45Chousukenote no parentheses around payout. :)
10:45koguah, that was where i was stuck
10:45Chouseror: (if-let [payout (odds roll)] (- payout 1) -1)
10:47kogucho: final question for you, I have a list of 2 random numbers, i have a odds table like this
10:47kogu(def odds {'(5 5 5) 25 '(4 4 4) 5 '(3 3 3) 5 '(2 2 2) 5 '(1 1 1) 5 '(0 0 0) 5})
10:48kogunow i need to check if i have 2 zeros 1 non zero
10:48koguwhat would be the lispy way todo this
10:49koguas i need to check for (0 0 *) (0 * 0) and (0 0 *)
10:49Chouseryou have a list of 3 numbers?
10:49koguyes, i have a list of 3 numbers (0-5 0-5 0-5)
10:50kogufor checking 3 numbers i made a map above
10:50Chousuke(= 2 (count (filter zero? triple))
10:50Chousuke)
10:51Chouserthough I had: (= '(0 0) (filter zero? triple))
10:52koguyes, that works perfectly
10:53koguinfact thats a better approach than the map for the 3 identical values
10:53koguty again
10:54koguany fucntion to check if all values are identical?
10:54Chouser(apply = coll)
10:55Chousukeheh.
10:57Chousukemany of these solutions have the "d'oh" look to the
10:57Chousuketem
10:57Chousuke...
10:57Chousukethem
10:57kogu(defn eval-roll [roll]
10:57kogu (cond
10:57kogu (apply = roll) 25
10:57kogu (= 2 (count (filter zero? roll))) 10
10:57kogu (= 1 (count (filter zero? roll))) 1
10:57kogu () -1))
10:57koguhow does this look
10:57kogui think im done
10:58Chouseruse :else instead of ()
10:58kogudone
10:58kogutime to benchmark against the java code, woohoo!!!
10:59Chouseryou're sure it matters?
10:59Chousukekogu: most likely it'll be a fair bit slower :)
11:00Chouserthe most important benchmark is LOC, or some more reliable measure of mental complexity.
11:00Chousukebenchmarking might make java look good but does the *code* look as good as the clojure equivalent?
11:00Chousukeor "equivalent" :/
11:02koguloc : 18 vs 57
11:02ChouserI wonder if condp would help here. I have no sense of how to use its features yet.
11:02Chouserkogu: ah, nice. That's worht so much more than 5 seconds vs. 1 second of processing time, or whatever.
11:03koguspeed : 7 sec vs 2, that's not bad
11:03kogucho: ty again, you are truly awesome
11:04Chouseryou could get back some or all of that speed, but it would start to cost you in code clarity
11:06danm_good morning
11:08kogugm
11:15koguany recommended profilers for clojure?
11:44RSchulzYourKit is what I use, though I've yet to apply it to Clojure code.
11:44RSchulzkogu: ^^^
11:44kogurs: ty
11:45kogudoes anyone of anywork on something like jsp's for clojure?
11:45koguas in, compile to servlets
11:46duck1123kogu: there's been varying amounts of success with compojure
11:46kogui did look into compojure, but right now there is no mention of any templating system
11:46koguits much better to write html and embedd lisp rather than the other way around
11:47duck1123it uses compojure.html to generate html from vectors
11:48koguduck: yeah, but i would like to write html file, and embedd bits of lisp in it
11:48duck1123There was a thread recently on that subject, I don't know how far anyone got
11:49kogucool, let me dig that up
11:49hiredmanugh
11:49hiredmanwhy would you want to write any html at all?
11:50koguhehe, work!!!
11:51koguis jvm good for anything else?
11:51Chousukes-expressions map nicely to HTML anyway
11:51qebabhey, is it possible to use keyword params or optional params?
11:53duck1123kogu: http://tinyurl.com/7vlcj6
11:53kogustep 1: download free html template
11:53kogustep 2: write clojure blogging system
11:53kogustep 3: ???
11:53kogustep 4: profit!!!
11:53hiredmansounds horrible :(
11:54Chouserqebab: http://groups.google.com/group/clojure/msg/51bb53ca077154f8
11:54hiredmancompojure's vector -> html deal is great
11:55Chouserqebab: that's some old code, so it could probably be written more concisely now. But at first glance it looks like it would still work.
11:58qebabChouser: I don't really need it, I just think it'd be convenient. :)
11:58qebabChouser: Thanks, though.
11:58Chouserif you just want some keyword args tacked on the end of zero or more positional args, you can do it in about one line
12:02Chouser(defn foo [a b c & keyargs] (let [{:keys [d e f]} (apply hash-map keyargs)] [a b c d e f]))
12:02Chouser(foo 1 2 3 :e 9) ==> [1 2 3 nil 9 nil]
12:39daswerthChouser: yesterday you wrote up something on unbuffered input to a text terminal: http://paste.lisp.org/display/72515
12:39Chouseryep
12:40daswerthI'm afraid I don't understand why there are to defn's for "system"?
12:40Chouserjust a pasting mistake on my part. The first is overridden by the second.
12:41Chouseras in, replaced. The first is completely unnecessary.
12:41daswerthah, great. :)
13:30klinkersbooya clojure is awesome
13:30zakwilsonWe've noticed. That's why we're here.
13:30klinkersa nice fairly pure functional language + a lot of good javalibs
13:31klinkersanyone working on machine learning stuff?
13:31Chouserpeople seem to ask about genetic programming a lot
13:31klinkersi working on webapp/mobile app using machine elarning for secret stuff and great profits!
13:32klinkersmaybe i will eb the first big clojure success story
13:33Kerris7I've been tinkering with the idea of writing a Chinese Chess a.i. in Clojure
13:34Kerris7should make for a decent final year project, but the other candidates are quite strong (Scala)
13:36klinkersfinal year of what?
13:37klinkersundergrad?
13:37klinkersi wrote an optimal-playing tictactoe in clojure but chinese chess is a little harder :)
13:38Kerris7klinkers: undergrad
13:43Kerris7klinkers: yes, a little harder :P http://en.wikipedia.org/wiki/Xiangqi
13:44ChouserKerris7: I was learning Scala before I abandoned it for Clojure, in case that's worth anything to you.
13:45Kerris7Chouser: I'm working on a portfolio that'll hopefully admit me to a good Master program and the existing material for that domain is mainly in OCaml
13:46ChouserKerris7: ah. sounds like you may have significantly different goals than I had.
13:46Kerris7Chouser: if you don't mind me prying, what were your intentions?
13:46Chouserfor a masters program, Clojure's non-invasive type system may look less impressive.
13:48ChouserKerris7: For years I'd been looking for a practical language that was very "expressive", or at least that's the term I generally use.
13:50Kerris7alright
13:50Chouser...which means something along the lines of getting the most done with the least amount of code, where the things being done are the sorts of things python and ruby have been good at: command-line tools, data and string wrangling, web apps, etc.
13:50gnuvinceHehe
13:50technomancyheh; I guess for education purposes, Scala has the advantage of looking more impressive since the type system is harder to use. =)
13:50Chousertechnomancy: exactly what I was thinking.
13:50gnuvince"Dude, Clojure is too easy, no way you're getting that Masters Degree!"
13:51gnuvinceThrow in partial continuations and amb in there to make it look more impressive
13:51ChouserI was skating through project euler problems in Scala, liking it just fine.
13:52ChouserThen I tried to write a nice API (a.k.a. embedded DSL) for querying XML documents.
13:52gnuvinceDidn't like it so much then?
13:52Chouserthe type system bit me hard. I was trying to use the code as I wrote it to help me think about the problem. When I got it into a state that seemed to express what I wanted, I still couldn't test it because my types were all messed up.
13:53ChouserI spent a few days trying to get my trivial 4 or 5 function system to actually compile.
13:54Chouserand even then the lack of macros meant my API wasn't as tidy as I wanted.
13:54Kerris7If I can find sufficient material on writing lexers with Lisp maybe I can muster up something with Clojure
13:55ChouserAnyway, a couple rhickey videos later, and I'd found a new home here. The result a similar project in Clojure is at clojure.contrib.zip-filter
13:56gnuvinceChouser: are you a Java refugiee?
13:56Chousernot really. I learned Java a tiny bit ages ago -- actually learned threading in Java -- but I've never liked it much.
13:57gnuvinceok
13:57gnuvinceI'm thinking I should probably learn Java
13:58ChouserI was giving the JVM a chance because Yegge talked me into Rhino, shortly before Project Euler talked me right back out of it.
13:58gnuvinceRhino...
13:58gnuvince*meh*
13:59ChouserWell, I thought I wanted an optional type system and C-like syntax.
13:59gnuvinceIs there a Java library to do like Python's struct.pack and struct.unpack?
13:59technomancythe way they promoted it early on was pretty weird--hey guys, you can use all these awesome Java libraries and package stuff up as a WAR file.
13:59gnuvinceNobody really wants C-like syntax; people just think they want it.
13:59Chousergnuvince: for C library interop, or more general binary data packing?
13:59technomancyand Ruby users look at the Java libs, and they have uniformly horrible APIs... and we have no idea what a WAR is, but it sounds violent.
14:00technomancyso it was hard to get excited about JRuby at first. =)
14:00hiredmantechnomancy: but uniformly documented
14:00gnuvinceChouser: general binary data unpacking
14:01Chousergnuvince: ah, don't know. sorry.
14:01technomancyhiredman: you only have to learn a library once; you have to deal with the API forever. =)
14:01gnuvinceChouser: thanks
14:01hiredmantechnomancy: you just deal with the api long enough to wrap it with something more sane
14:02hiredmanjavadoc is a life saver
14:02technomancywell, the only Java libraries I've used have been jakarta httpclient (wretched, horrible API) and ROME (decently usable, but the docs weren't very good)
14:03technomancywhy you'd name a library after Jakarta is beyond me; I've been there, and it's a pretty miserable city.
14:04hiredmanmaybe that is why they renamed it to apache commons
14:04Kerris7maybe it was mainly developed by programmers from the city :V
14:06leafwlikely it was chosen beause of the 'j' in the name.
14:06hiredmanheh
14:06lisppaste8drewr pasted "atom exception -- how is this possible?" at http://paste.lisp.org/display/72540
14:06technomancyleafw: probably. It's a good warning for what happens when you pick a name without doing research first.
14:07drewrI think there's either a bug in atom or swap!.
14:07hiredmansomeone in #java just asked about a "macro system" for java, and someone said "macros are for desktop apps like word and excel or for editors."
14:07drewrSomehow iref is nil in get-validator.
14:07Chouserdrewr: got any code to reproduce it?
14:08technomancyheh
14:08leafwhiredman: difficult to preach to the blind.
14:08Kerris7or the deaf
14:08drewrChouser: I'm trying to distill. My smaller test cases aren't triggering it.
14:08Chouserdrewr: are you using validators?
14:08drewrI thought I would start with the exception first, because it's pretty strange.
14:10Chouserdrewr: I can replicate the top 3 lines of that stack trace with: (swap! nil inc)
14:11lisppaste8drewr annotated #72540 with "possible sample code" at http://paste.lisp.org/display/72540#1
14:13Chouserdrewr: so if your agent's map ever loses its :foo key, you'd get that exception.
14:14drewrChouser: I'm trying to see if that happens.
14:15drewrDangit, it's nil. This thing is supposed to be immutable! :-)
14:17Chouserhm, the agent? not likely. :-)
14:17technomancyhas anyone here tried hashdot? (http://hashdot.sf.net) it seems to make the JVM CLI experience somewhat less onerous.
14:17drewrChouser: No, the map :-)
14:41gnuvinceHow come (reduce str xs) is so much slower than (apply str xs)?
14:42hiredmanstr makes stringbuilders I believe
14:43hiredmanso reduce ends up instanciating a lot more objects
14:45gnuvinceHow does apply avoid that?
14:48rhickeygnuvince: a single call to str creates one StringBuilder, and apply is a single call to str
14:48rhickeyreduce is many calls to str
14:50gnuvinceapply creates a single StringBuilder and calls .add() (or whatever the name is) n times while reduce creates n StringBuilders and calls .add() only once on those?
14:52rhickeygnuvince: it's best to forget about str - apply calls a fn once with a sequence of args, reduce calls it once for each pair of elements. str optimizes the concatenation of its args, but can't across calls
14:55gnuvinceok
14:55hiredmanthe "namespaces, keywords, and symbols" looks like it might need a faq entry
14:57duck1123Does anyone know if a SVG version of the clojure logo exists?
14:58RSchulzhiredman: Whatever makes you think that??
15:01hiredman:P
15:16hoeckduck1123: clojure-glyph.svg in the files section of the google group
15:21Chouserit only seems complicated if you try to think about it
15:22hiredmanChouser:?
15:22Chousernamespaces, vars, symbols, keywords. They all work very naturally almost all the time.
15:23hiredmanyes
15:23hiredmanI don't mean it is complicated, I mean there are two different threads in group about it, so maybe it is a faq
15:23Chouserit's only when you try to think about edge cases or unusualy usages that it starts to seem complicated.
15:23Chouseroh
15:27Chouserit does seem a bit hard to pin down what should go in a faq vs. an appropriate place in the regular docs.
15:29hiredmanwell
15:29hiredmanthings that are asked about frequently can go in the faq?
15:29Chouserif the docs were complete, would they still be asked about frequently?
15:30hiredmanthe only way to find out is to complete the docs
15:30Chouserif I want to learn about topic X, do I need to read it's section in the regular docs plus in the FAQ in order to get a complete picture?
15:32hiredmanif the docs clear it up, and people stop asking about it, it can be removed from the faq
15:32hiredmanit's not like this is being carved in stone, it's html
15:38technomancyis it safe to say atoms are meant for idempotent actions?
15:40Chousernot necessarily.
15:41ChouserSomeone mentioned on the group the function of generating unique ids, where skipping an id is acceptible. atom would work fine for that.
15:42technomancythat makes sense
15:47klinkersif i have a file main that uses the namespace progs.someapp.donkey and progs.someapp.horse and they both happen to have a function group-by. now, how do i refer to each group-by in main?
15:49Chouserif you try to (use ...) both of them, it should complain on the second one.
15:52Chouserklinkers: so you can either do (use '[progs.someapp.horse :rename {group-by horse-group-by}])
15:53Chouseror (require '[progs.someapp.horse :as horse]) and say (horse/group-by ...)
16:47hiredmanwhy don't explanations of what a monad is make sense?
17:04Chousukehiredman: actually, reading through the wikipedia explanation I think I can see some sense in it.
17:05hiredmanthen you are a better man than I
17:06Chousukehiredman: it seems monads can be used to specify semantics to computations without affecting the "functional" nature of the values those computations return
17:06hiredman*woosh*
17:07ChousukeI think the Maybe monad is pretty simple to understand: the computation can fail, so the Maybe monad wraps the value in something that can tell you whether it failed or not.
17:07amit_any idea why i might get an IllegalAccessError trying to invoke a constructor for a java class even though I'm able to import it succesfully ? (I'm on the clojure prompt)
17:08Chousukebut if it doesn't fail, the result is safe to extract from the monad and treat as if it were just another value
17:08hiredmansounds like Just Another Object
17:11Chousukefor IO I guess the IO monad "describes" the IO required to get the value (a string, for example), but once you have the value and have extracted it from the monad, it's immutable just like any other value
17:11Chousukeso monads give you a way to explicitly define that something else than just functional value computation is going on, and work with that.
17:12hiredmanuh huh
17:50drewrIs there any way I can get @@(send-off (agent :a) (fn [x] (send-off (agent :b) (fn [y] y)))) to work?
17:50drewrWork == return :b immediately.
17:52Chouseryou want the top-level expression to not return until both agents have updated their status?
17:53Chousers/status/state/
17:53drewrYes, that would be ideal.
17:54Chouserusing agents synchronously like this is a bit non-idiomatic (are you sure you don't want refs?) which costs you some complexity, but it can be done.
17:54drewrIn my use case, :a is a long-running thread which fires b's off periodically. What happens is b agents are return immediately, but their actions aren't fired until what seems like too late.
17:55Chouser'sends' done in an agent's action are held until the action is complete. this is a feature.
17:56Chouseragent :a is in some kind of loop, but not sending to itself?
17:57drewrYes, :a is doing something similar to (loop [] (something-that-eventually-fires-b) (Thread/sleep ...) (recur)).
17:58Chouserit might help to (send *agent* thisfn) instead of recur. That will allow other sends to go as well.
17:59drewrYou mean recurse by creating another agent?
17:59hiredmanthis might also be faq worthy
17:59Chouserdrewr: no, recurse by sending to your own agent again
18:00hiredman*agent* is bound to the current agent inside an agent action
18:00Chouserdrewr: this is how at least one of the agents behaves in Rich's ant demo
18:00drewrAh. Hm, let me look at that.
18:02hiredmanman, I miss clojurebot
18:02hiredmanit's like phantom limb
18:02drewrOK, (send-off *agent* #'behave).
18:04hiredmanclojurebot: FAQ#2 is sends and send-offs that occur in an action sent to an agent do not take place until the agent's state changes
18:05Chouserdrewr: right, though there's no need for the #' prefix anymore
18:06Chousukehiredman: talking to ghosts now? where is clojurebot, anyway?
18:06hiredmanhard drive died, so I need to rebuild the machine
18:06Chousukeah.
18:06drewrChouser: So send* won't consume the stack?
18:07drewrIt will just fire off new threads and the old ones gc?
18:07Chouser(send (agent 9) (fn act [v] (prn v) (when (pos? v) (send *agent* act) (dec v))))
18:07hiredmancute
18:08Chouserdrewr: even better, it will probably return the current thread to the pool before the new one is needed, so it may even use the same thread.
18:08Chouserbut yes, no consumption of finite resources
18:10Chouserinteresting -- using 'send' on this dual-core laptop, the action is indeed run on the same thread each time.
18:10drewrSweet.
18:11Chouserusing 'send-off' it oscilates between two threads.
18:11ChouserI wouldn't bet too heavily on either behavior in any given circumstance, of course.
18:12Chouserdrewr: so that'll get your sends to agent :b going periodically. you still need the top-level thread to wait until they're all done?
18:13drewrIn this case, :b is a network connection, and :a watches to see if any die and restarts them.
18:14drewrStarting works great, but the restarts involve the nested agent issue.
18:14Chousersure.
18:14drewrEach connection has a listener agent which is another long-running loop that's doing (read-line) on the input stream.
18:15drewrThese listener agents (and their associated async msg queues) don't ever have their actions fired.
18:15drewrPresumably that's because of my infintely loop-recurs that don't return.
18:16Chouserright. another benefit of the re-send looping is you can swap in a new definition of your function at runtime and the next send will pick it up.
18:16drewrAh, yes.
18:24drewrSo in (send *agent* foo), does the arg to foo become the future state of the first run through foo?
18:25Chouserno, the return value of the action becomes the new state of the agent.
18:25Chouserin that little example I posted above, I did the (dec v) after the (send ...)
18:26drewrThat's what I was basing that on. I think you said what I meant by my question.
18:26drewrJust didn't express it clearly.
18:26Chouser:-) ok
18:54arohnerI'm trying to read out of a socket, and BufferedReader.read() wants a buffer to fill up. What is the easiest way to create a buffer from clojure?
18:56Chouseryou want the classic char[] variety?
18:56arohnerah, make-array
18:56arohnerChouser: yes
18:56Chouserright, (make-array Character/TYPE 1024)
18:57arohnerthanks
21:28arohner(java.util.regex.Pattern/matches "(.+): (.+)" "Host: localhost:1344")
21:28arohnertrue
21:29arohneruser> (. #"(.+): (.+)" (split "Host: localhost:1344"))
21:29arohner#<String[] [Ljava.lang.String;@19ad02>
21:29arohneruser> (alength (. #"(.+): (.+)" (split "Host: localhost:1344")))
21:29arohner0
21:29arohnerThat is *completely* unhelpful
21:29arohnermatches with zero length?
21:35Chouser(re-seq #"(.+): (.+)" "Host: localhost:1344")
21:36Chouserthe regex matches the entire string, so it's a match and you get an array
21:36Chouserbut the contents of the array are the pieces of the string separated by what matched -- which is nothing.
21:39arohneroh, I needed to use re-matches
22:07pjb3Hey, I have a solution for Paul Graham
22:07pjb3's Accumulator Generator in Clojure: http://github.com/pjb3/accgen/tree/master/accgen.clj
22:07pjb3This seems pretty good, any ideas on how to do it differently?
22:08hiredmanlisppaste8: url?
22:08lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
22:10hiredmanpjb3: http://paste.lisp.org/display/70873
22:11pjb3hiredman: huh?
22:11hiredmanits a counter
22:12pjb3The problem: Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i.
22:12hiredmanso how c works is
22:12hiredman(c 3) returns a function
22:13hiredmanwhich returns a function, etc
22:13hiredmanuntil you pass the function something not a number
22:13hiredmanat which point it tells you how many times you called the function
22:13pjb3hiredman: well, that's nice, but I don't see how that's a solution to the problem
22:14hiredmanit is a subset of the problem, the case where you increment by 1
22:15hiredmananyway
22:16pjb3hiredman: It's a solution to a different problem
22:16hiredmanI did not read the problem, I just saw "Accumulator Generator"
22:16pjb3(let [acc (foo 1)] (acc 20) (acc 21))
22:16pjb3should be 42
22:17pjb3I think the original intent of the problem is basically a test to see "does your language have closures and lambas"
22:17pjb3Which PG considers to be important things
22:18pjb3but the other thing you need is mutable state
22:19pjb3This works pretty much the same way, except you have to give the function access to the atom as a closure
22:33doublefreeHi all, I'm new to Clojure, and I wonder what is a fast way to select a (or n) random element(s) from a potentially large set?
22:35doublefreeI'd like to avoid converting the set to a vector if possible
22:40pjb3doublefree: Off the top of my head, I don't know of a way to do that without converting it to a vector
22:42doublefreepjb3: ok - perhaps it is my data's destiny to live in a vector after all
22:42pjb3doublefree: Does this help? http://stackoverflow.com/questions/124671/picking-a-random-element-from-a-set
22:47doublefreeI see the proposed Lisp solution there reflects my initial approach (the following doesn't work because PersistentHashSet does not support nth which makes sense I suppose): (defn pick-random [set] (nth set (random (count set))))
22:47pjb3huh, sets aren't seqs?
22:48pjb3doublefree: Yeah, I was just trying that, but ran into sets not being a seq
22:49hiredmannothing is it's own seq except lists
22:49hiredmanbut seq knows how to turn sets into seqs
22:49hiredmanuser=> (seq #{:a :b :C})
22:49hiredman(:b :a :C)
22:50pjb3(defn pick-random [set] (let [sq (seq set)] (nth sq (rand-int (count sq)))))
22:53doublefreepjb3: thanks works well enough for now!
22:53pjb3doublefree: yeah, not sure if that's "fast"
22:53pjb3is (seq #{...}) O(n)?
22:54pjb3Or is there some fast way under the covers of making a lazy-seq from a set
22:55pjb3clojurebot: ?
22:56hiredmanI have the new hard drives for the clojurebot machine
22:56hiredmanso it will be back soon
22:56pjb3anyway, the docs for nth say it takes a coll, and the docs for sets says it is a collection
22:57pjb3Right, and (coll? #{}) is true
22:57pjb3so, that's a little confusing
22:59hiredmanmaybe something to mention to rhickey
23:08Chouseralmost none of the collections are seqs, but all provide efficient (generally lazy) seqs when you pass them to seq
23:09Chousernth doesn't work on all collections, and unlike some functions doesn't apply seq to its parameter
23:09hiredmanyeah I just looking at the source in google code
23:09drewrI changed some sends I had to send-off and certain things started working and I have no idea why.
23:10hiredmanmaybe it should say "only works on certain collections"
23:10hiredmanI take that back
23:10hiredmanthe doc string doesn't say it takes collections
23:10hiredmandon't know why I thought it did
23:11Chouserit uses 'coll' as the arg name
23:11hiredmanshort for collar of course
23:47doublefreeI find it strange that (first #{1 2}) and (second #{1 2}) work while (nth #{1 2} 0) does not... I see first and second call seq on their args, and apparently nth does not. I wonder why this is.
23:47Chousernth can't be any faster that O(n) on a seq
23:47Chouserbut it it works in O(1) time on vectors, array, etc.
23:53doublefreeyes, but nth could seq its arg if it's not of a class that provides constant time lookup itself and in doing so provide a more consistent interface. anyways no biggy.