#clojure logs

2009-06-24

03:27Lau_of_DKTop of the morning gents
03:27cgrandmorning Mr Lau!
03:50frodefso how do I specify the method class signature with proxy? I need one object with two methods with the same name but different argument classes..?
03:51frodef(mymethod [#^the-class arg] ...) seems not to be right?
03:59hiredmanfrodef: you don't
03:59hoeckfrodef: proxy maps a clojure fn to each method-name, so you have to dispatch inside the fn
03:59clojurebotproxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.
03:59hiredmanwhat you do is you put a cond or similar inside the method
03:59frodefah, ok. So both methods in the interface maps to the same-named fn. Thanks.
04:36frodefhow do I ask wheter a value implements a certain interface?
04:36frodef(or is of a certain class?)
04:36frodefah, instance?
04:37frodef..for classes, but not interfaces.
04:38frodefurgh, for interfaces too. I got the argument ordering wrong. sorry about the noise.
06:33frodefhow do I round a number to nearest integer? e.g. (round 10 3) -> 3
06:33frodef..or (round (/ 10 3)) -> 3
06:35sunwukonground found in clojure.contrib.math works like your second example
06:37frodefok, thanks.
06:43AWizzArdGeneral question for your opinion: do you know/think that it is allowed to have a (clojure) program automatically gathering information from a website? For example look up automatically 3000 words in a dictionary?
06:45sunwukongimho legally: yes ; morally: depending on the actual server/amount of data
06:45dhayaAWizzArd: The same rules that apply for search engines crawlers apply. (robots.txt etc). Also, hitting the site without sufficient pause time, will likely get your IP banned.
06:55AWizzArdah good, the robots.txt should help, thanks you two
08:36rhickeysweet, this is what's nice about being on the JVM. Had updated my os x java vm, now includes VisualVM...
08:37rhickeyso I type jvisualvm at a prompt, VisualVM comes up, calibrates for my machine, show a gui, oh look, there's my (already running) repl session, connect, start getting monitoring, proifiling etc
08:40rhickeynot as powerful as yourkit, but handy
09:02Chouserrhickey: I think you have enough earnings from Clojure T-shirts to offer a bounty for contrib.jar
09:02rhickeyChouser: heh, now I need to bribe, eh?
09:03mblinnwell you could pay in t shirts
09:03Chouserbah, a couple dollars short, at least for some shirts.
09:03Chouserrhickey: just making you aware of your options. :-)
09:04rhickeythanks
09:04Chouserah, it looks like any white T would be covered.
09:06rhickeyhmm, I see "What would it take?" implies a bribe possibly
09:07rhickeyHave been working on pre/post conditions
09:07Chousercool
09:09rhickeysomething like:
09:09rhickey(defn foo
09:09rhickey #^{:pre [(even? x) (< x y)] :post [(not (nil? _))]}
09:09rhickey [x y] ...)
09:09rhickeyeventually some mojo to make that:
09:09rhickey(defn foo
09:09rhickey [x y]
09:09rhickey {:pre [(even? x) (< x y)] :post [(not (nil? _))]}
09:09rhickey ...)
09:10rhickeybut still yielding the map as metadata on the arglist
09:10ChouserI've been telling people that Clojure will probably eventually have some kind of compile-time assertion system where "classic" static typing would be a subset. Is that roughly true?
09:10rhickeythus tools could find and display via metadata
09:11rhickeyChouser: that's one idea, built on some type of built-in logic lang like datalog/prolog
09:11Chouseryeah, ok. That was my impression.
09:11rhickeywould be a hybrid of checker and analysis tool
09:12rhickeyone point on the post conditions is how to label the return value (_ above)
09:12Chouserruntime pre/post is good too of course. Do you imagine it being used mainly during testing and turned off during production?
09:12rhickeyoptions are _, or the fn name (would require it be named)
09:13rhickeyChouser: that depends on the app, so there will have to be some flags
09:13Chouser_ elsewhere has come to mean "I don't care" ... might be pretty confusing to overload that meaning here.
09:13rhickeyconsidered assert no/yes/condiionally (supply a var)
09:14rhickeyChouser: agreed, _ means don't care everywhere else
09:14achimhow about making % readable outside #(...) for such things (similar to unquote)?
09:14rhickeycould use a fixed name, like 'ret'
09:14rhickeyachim: I have though about that
09:14Chouserachim: I was wondering that too
09:15rhickeyone problem is that it would allow a lot of errors to flow through and become 'I don't understand %', also would let people do (let [% 42] ...)
09:16rhickeyright now when you see % you know you are in an anonymous fn def
09:16Chouserpeople can already do (binding [map filter] ...) Just because it's bad doesn't mean it has to be forbidden.
09:16rhickeyagreed
09:17rhickeyone other point was possible destructuring of return value for post
09:17Chouserhmmm
09:17rhickeyelse :post [(let [[x y] %] ...)]
09:18rhickeyok if only one test, tedious if more
09:19Chouserright, but giving a spot in which to name the rtn value would solve both the naming and destructuring at once.
09:19rhickeyChouser: that's something different altogether, seems like a hassle
09:19Chouser:rtn rtn :post [(< 5 rtn 10)]
09:20rhickeyI don't like it separate from post
09:20Chouseryeah, that was to avoid :post [rtn (< 5 rtn 10)]
09:20rhickeyexactly
09:21rhickeybut :post [aname ...] is the best I could come up with, just irregular
09:23rhickeyeither name is always required, or must be a symbol/vec/map binding form
09:23rhickeywill work until we have lists as destructuring forms :)
09:26ChouserI don't think 'always required' is so terrible, but changing from binding to test exprs without sentinel in a single vector's a bit tricksy
09:26rhickeyagreed, not done anywhere else
09:27lpetitwhy not a short and a long form ?
09:27Chouser[:pre (< 5 x) (even? x) :post [rtn] (< 5 rtn 10) (odd? rtn)]
09:27Chousereh.
09:27achimmight type-based preconditions eventually be a way to avoid boxing/unboxing of numbers? i.e. if the args to a function are constrained to be ints, would it be possible to generate bytecode that took unboxed ints as arguments?
09:28rhickeyachim: no
09:28ChouserI was thinking having the binding form always in a vector might help it stand out, but that doesn't really look much less confusing.
09:28lpetitshort form takes directly a vector of forms
09:28lpetitlong form takes a map with :rtn (taking possibly a binding) , :tests (or something else) taking the vector of forms
09:29rhickeyChouser: plus the result is still a to-be-parsed bag
09:29Chousernot much point if the long form is longer than (let [[x y] %] (and ...))
09:29rhickeylpetit: I'd really like to avoid that kind of thing. ns/require/use are the most complicated parts of Clojure for that reason
09:30lpetitrhickey: I understand
09:30Chousernow's not the time to discuss, but I'd love to require removed and 'use' simplified. I think it can be done.
09:32lpetithaving the output follow a given "destructuring form" may convey enough information on itself to deserve not being mixed with other post conditions.
09:33frodefis there some variable somewhere that limits the size of stacktrace that gets printed?
09:33rhickeyI'm going to work on the presumption that multi-test postconditions requiring destructuring will be rare
09:33frodefI have a stack overflow that I find it hard to find the source of.
09:34Chouserfrodef: you might look at clojure.contrib.stacktrace
09:35lpetitSo maybe having along with :pre and :post some :rtn-struct (I'm really bad at naming things :-(.
09:35lpetitIf no :rtn-struct (or some really better name!) is provided, then use % or the function name or whatever you come up with as a default value to reference the return value in the post conditions
09:35lpetitIf :rtn-struct is provided, then the symbols (either a simple one to name the result, or more complex ones when destructuring is leveraged) are provided for each form in the :post vector ?
09:35clojurebothttp://clojure.org/data_structures#toc10
09:36frodefChouser: ok, thansk
09:38lpetitso the simple case : :post [(pos? %)]
09:38lpetitthe moderate complex case :ret-struct [k v] :post [(not (nil? k)) (not (nil? v))]
09:38lpetitnote that :ret-struct could then be used to externally document the structure of the return value. Maybe I don't like that so much, because we do not separate whether the destructuring is used for documentation or for not DRYin the post-condition code ...
09:39lpetitIn the same time, the post condition code serves as documentation ....
09:40Chouserlpetit: the docs point is interesting -- very similar to how args are used now: destructuring for practical as reasons, but by default included in the docss.
09:42frodefhm.. these lazy lists are no fun debugging, are they.. :)
09:43Chouserfrodef: can be a bit tricky. if you can handle a dorun temporarily, that sometimes helps.
09:44lpetitChouser: maybe just the name :ret or :rtn instead of :ret-struct could be sufficient : it would document if anything is guaranteed by the function in terms of structure (even a single symbol is an explicit information that *nothing* is guaranteed, which is an indication)
09:44frodefChouser: doall should do the same, no?
09:45lpetitBut maybe it is too early and overlapping with the general problem of how to optionally expose type information
09:45Chouserfrodef: well it de-lazy's your seq. Might be unacceptable depending on why your seq is lazy, but if it's ok it may shorten your stack trace and make things happen in a dynamic context that is less surprising.
09:46Chouserlpetit: except it's so nicely symmetric with input args.
09:51weissjwhat is the clojure equivalent of mapcar?
09:52Chouserweissj: I think just 'map'
09:52lpetitChouser: yes, indeed. So you like the idea ?
09:53Chouserlpetit: well, I like the idea of having a place to explicitly declare return value destructuring for use in docs and post conditions. Haven't seen a syntax I like yet though.
09:55Chouser(defn [a b c] :rtn [a] ...) except that looks like it might return the value of arg a, which is of course completely wrong.
09:55lpetit:returns ret-name :post [(pos? ret-name) (even? ret-name)]
09:55lpetitor :returns [key val] :post [(not (nil? key)) (pos? val)]
09:55lpetitinserted in the map along with :pre , :docstring ... keys
09:56Chouserlpetit: I don't think that's terribly, but rhickey already said he didn't like it separated from the :post exprs.
09:56Chouserterrible
09:58lpetit(defn foo #^{ :pre [(even? x) (< x y)] :returns [k v] :post [(not (nil? k)) (> v y)] } [x y] ...)
09:59lpetitChouser: well, the args names are separated from the :pre, and that seems not to be a problem, though :-)
09:59Drakesonassume (f l) -> [l1 l2]
09:59Drakesonhow can I partition a list by iteratively applying f to the current list, spitting out l1, and keep l2 as "current list"? is there a way better than loop?
09:59lpetit,(doc partition)
09:59clojurebot"([n coll] [n step 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."
10:00lpetitoh no
10:00ChouserDrakeson: example?
10:01ChouserI don't really understand what are in l1 and l2
10:01lpetit,(doc split-with)
10:01clojurebot"([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"
10:03Drakesonassume I call it partition-with. (partition-with #(split-at 3 %) (range 1 10)) -> [(1 2 3) (4 5 6) (7 8 9)]
10:05Chouserahh
10:06Chouserreturning a vector means non-lazy, so it can be built on reduce
10:06frodefincreasing the jvm's stack size seems to help me.. consequently I suspect that the zip-filter.xml uses stack O(n) to the XML input size?
10:07DrakesonChouser: laziness > vector, assume it returns a list then.
10:13Drakeson,lisppaste
10:13clojurebotjava.lang.Exception: Unable to resolve symbol: lisppaste in this context
10:13Chouser,url
10:13clojurebotjava.lang.Exception: Unable to resolve symbol: url in this context
10:13Drakeson~paste
10:13clojurebotlisppaste8, url
10:13lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
10:14lisppaste8Drakeson pasted "partition-with" at http://paste.lisp.org/display/82424
10:14Drakesonnow, that is not equal to some other function we already have, right?
10:16ChouserDrakeson: I don't think so.
10:16Drakesonthanks
10:16Chouserfor some cases, contrib.seq-utils/partition-by might suffice, but it's doing something a bit different.
10:17DrakesonI stole it from partition-by
10:17Chouseroh, ok.
10:17Drakeson(modified it a bit)
10:17Drakesonbtw, I need that function for parsing.
10:18ChouserI think partition-by could be written using split-with and your partition-with
10:32lpetithttp://clojure.org/lazy says "lazy-seq goes at top level of lazy sequence function" , and also "lazy-seq and delay both perform closed-over local clearing on the tail call of their body", so my question is : could there be a problem with the pasted partition-with code ? if not, are there corner cases where not placing lazy-seq as the top level form of lazy sequence function could have memory...
10:32lpetit...problem ?
10:39lpetit?
11:45rhickeyDrakeson: that code is not fully lazy
11:46Chouserbtw, someone pointed out that reduce on range is slower in chunked than master.
11:47ChouserI had to chain 2 or 3 more chunked operations before the chunking was a win over the Range object.
11:47rhickeyChouser: I know, I took out the IReduce special paths in order to see what matters, reduce on range being a nice demo but not typical
11:47Chouserright
11:48tsdhHi. I'm currently transforming some clojure code into an eclipse projects to make it appealing to my colleagues.
11:48rhickeyjust added reduce on the chunks themselves, with other tweaks today (reduce + (filter even? (map identity v))) almost 2x as fast as yesterday (in chunks), and 5x as fast as pre-chunks
11:49tsdhIn one clojure app, I use some images in the GUi. Now I have the code in src/foo/bar/baz.clj and the images in icons/*.png. But I don't have a clue howe to reference them...
11:50tsdh(ClassLoader/getSystemRosource "icons/a.png") returns nil. Adding several ../ in front doesn't make it happy, either.
11:50Drakesonhow would you serialize an object into a file? would you use spit and pr-str ?
11:51stuartsierraDrakeson: yes, or open a writer and use pr
11:52Drakesonhow would you get rid of *print-level* and *print-length* temporarily?
11:52Drakeson,*print-level*
11:52clojurebot30
11:52stuartsierra(binding [*print-level* nil, *print-length* nil] ...)
11:52tsdhI think in Java I would use getClass().getResource(relativePathFromThis), but that has no equivalent in clojure, afaikt.
11:52Drakesonaaah, that's it, thanks.
11:55tsdhOh, using simply (ImageIcon. "icons/a.png") works. Well, most often the simplest solution is still the best.
11:55tsdh;-)
12:09baetis-flyCan anyone explain when you'd want to use definline?
12:09opqdonutfor performance reasons i guess
12:10Chouserif you want to take or return primitives in some cases, but allow your fn to be used in other higher-order cases as well.
12:11baetis-flyLet me be more specific. In compojure, there is a definline servlet which takes a function and creates a proxy servlet for the route. If I called (servlet) in the same namespace as my route (function) then i can do hot reloads when i redefine the function. When i call it from another namespace, that no longer works.
12:12Chouserbaetis-fly: link to that code?
12:13baetis-flyChouser: sure, one sec.
12:14baetis-flyhttp://github.com/lrenn/compojure/blob/4a2079d1a28cddcb174c4a7f650c6a70e3258f31/src/compojure/http/servlet.clj
12:16baetis-flyIt's that "automatically updates if the routes binding is redefined" part that stops working when i move the servlet call into a different namespace than the route definition.
12:18ChouserI'm not sure why that's not a macro. Clearly there's something I'm not getting here.
12:19baetis-flyChouser: That's what I thought. Which is why I asked what definline was used for. I'm just not sure why James is doing it that way. I'll goto the source. Many thanks Chouser.
12:34combasamorning
12:35rhickeywhat's the best way to push a local branch to github and have it be tracked? github's recipe here: http://github.com/guides/push-a-branch-to-github seems to leave it untracked
12:36rhickeylast time I had to delete local after push, then branch --track, seems wrong
12:36Chouserrhickey: you mean you want plain "git push" and "git pull" to operate on that branch?
12:37rhickeywhen in that branch locally, yeah
12:37rhickeythat's how chunks is working
12:37Chouseroh, I see. I'm still learning how to use git against a git remote (instead of svn remote)
12:37combasaI wish I knew more about git, im just learning
12:38ChouserI've edited .git/config manually before, but I bet that's not right.
12:38Chouseror rather that there's something better.
12:38Chousukeuse git config :P
12:39rhickeyfor chunks I did git push origin chunks, git branch -d chunks, git branch --track chunks origin/chunks
12:39Chousukebasically, you need to set configure branch.<name>.remote and branch.<name>.merge
12:39rhickeycouldn't find a way to push with tracking
12:40Chousukeso git config branch.chunks.remote origin; git config branch.chunks.merge chunks
12:40rhickeyChousuke: I understand, but, ugh
12:40Chousukeactually, if the remote is origin, the first config is unnecessary
12:42rhickeythis recipe seems oriented towards knowing you want a remote branch up front:
12:42rhickeygit push origin master:refs/heads/some_branch
12:42rhickeygit fetch origin
12:42rhickeygit branch −−track some_branch origin/some_branch
12:42rhickeygit checkout some_branch
12:46Chousukegit checkout -b branch origin/branch sets up tracking by default
12:46Chousukehmm
12:47rhickeyChousuke: that's not the scenario
12:47combasaya i was going to say wouldnt `git checkout -b mybranch master` make mybranch your current branch, then you could setup remote and push be pushing with that?
12:47rhickeylocal branch exists, want to create on remote with tracking
12:47Chousukewell, for that you'd need the two git config commands.
12:48Chousukethen just push
12:48rhickeyusing commands, not config file editing
12:48rhickeyChousuke: I get the config file method
12:48Chousukeas I said earlier, just: git config branch.chunks.remote origin && git config branch.chunks.merge chunks
12:48Chousukecould probably make an alias for that.
12:49combasahaven't tried but why not setup branches in their own directorys then you dont need multiple configs each repository would have its own, not sure how you'd setup a branch in a different directory though
12:52combasaI'm going to have to re-read `git help branch` again I see
12:53Chousukeyou can't really have a branch in a different directory other than by cloning
12:54Chousukebut clones of local repositories are cheap, as git just uses hardlinks whenever it can
12:55combasayeah I realised it was a dumb idea :P
12:56combasaactually that reminds me, I wanted to ask.. if I wanted to start looking into the clojure source where would be a good place to start?
12:56Chousukewhich part of the source?
12:56combasayes which part
12:56ChousukeI mean, the java or the clojure side? :)
12:56Chousukecore.clj is pretty easy to understand.
12:57Chousukethe java stuff... not quite. :P
12:57combasaI'll have a look there then
12:57combasawhere would be a good java place to start?
12:58ChousukeI haven't looked at it much :)
12:58ChousukeI guess it depends on what you want to know.
12:59combasais the goal to have it all done in clojure at some point?
12:59Chousukewell, most, anyway
12:59Chousukebut that's probably not going to happen very soon :/
12:59combasawell I don't think it really matters either way does it
13:01Chousukehmm, interesting
13:01Chousukethere's a Seqable.java~be56ab81e88f8001494058a055089e982595c453 in my clojure source tree. in src/jvm/lang :P
13:01Chousukelooks like it's untracked.
13:07amunitehi all. i'm following http://yusupov.com/blog/2009/basic-clojure-setup-part-1/ to setup clojure in os x, but i cannot make it work. java is unable to find clojure.jar at all. any advice or clue?
13:08combasado makes use .bashrc files? im on linux
13:08combasamac's I mean
13:09kotarakWhen you use bash... then "yes" I suppos.
13:09combasaI see, maybe I'll just have a look at the guide first
13:09Chousukeby default, Terminal.app uses login as the shell, so it uses .profile
13:09Chousukebut if you use bash then bashrc will matter too.
13:13combasahmm that guide smells a little funny to me
13:16technomancyit's pretty old
13:16technomancywell, sort of old.
13:17technomancyI guess the move to git is recent enough not to call it old. =)
13:26JomyootIs there a web framework for clojure?
13:27combasaI believe enclojure is a web framwork, but I haven't looked at it yet
13:27slashus2~compojure
13:27clojurebotcompojure is http://github.com/weavejester/compojure/tree/master
13:28slashus2~ring
13:28clojurebotring is http://github.com/mmcgrana/ring/tree/master
13:28combasaah right, compojure
13:28Jomyootanything close to rails?
13:28combasawhats enclojure?
13:28slashus2A netbeans plugin for clojure.
13:28combasaah right
13:28Jomyoothow is performance of enclojure vs. scala?
13:44slashus2Could count be made chunk aware?
13:58quidnunccgrand: Can you give me an example of how to use the text-node selector?
14:00cgrandquidnunc: at last :-)
14:02cgrand(select nodes [:abbr :> text-node]) should return a seq of string
14:03quidnunccgrand: Sorry, different time zone + work makes it hard for me to catch up with you.
14:04cgrandand I'm sorry that today I have to run pretty soon
14:04quidnunccgrand: Me too :)
14:04cgrandquidnunc: mail me
14:05quidnunccgrand: :abbr is a placeholder for a tag name?
14:05cgrandyup but it's also a real tag-name
14:05cgrandhave to go
14:05quidnunccgrand: Thanks
14:09lisppaste8slashus2 pasted "chunk count" at http://paste.lisp.org/display/82446
14:09slashus2What do you all think of this?
14:13slashus2There are probably some improvements that could be made to the code, but you get the idea.
14:14cemerickwow, almost a 2x speedup.
14:14slashus2yup
14:14cemerickshould I expect the chunked stuff to make all seq operations faster in general (map, filter, etc)?
14:14slashus2Range has taken a pretty significant performance hit from generating a chunked seq though.
14:14Chouser(count (range ...)) is constant time on master
14:16slashus2Chouser: I looked at the code in RT and it looked like it incremented a counter.
14:16Chouserslashus2: what you've got seems reasonable. I wonder if chunk producers other than range would see much benefit.
14:17slashus2Chouser: I guess range's performance will increase later..
14:18Chouserslashus2: RT.count uses a counter if the collection is not Counted.
14:18ChouserIf it's Counted, it asks the object to count itself -- for things like vectors and Range, this is constant time.
14:20slashus2I see.
14:20slashus2I guess we could also make chunks Counted...
14:21Chouserbut on the chunked branch, range does not use Range, so your chunk-count has benefit there.
14:24Chouser (let [v (vec (range 1e6))] (time (chunk-count v)))
14:24Chouserit's interesting to compare that with core/count.
14:25Chouseroh, nm
14:25Chouserthat's just showing that chunk-count should check for 'counted?'.
14:26Chouser(time (chunk-count (map identity (range 1e6))))
14:26ChouserI think that's closer to what I meant to test. Looks like chunk-count still helps quite a bit.
14:27Chouserslashus2: I think rhickey is accepting chunked versions of seq-processing functions.
14:30rhickeyslashus2: counting non-counted things is a waste, making faster not that important
14:31rhickeyslashus2: range is work in progress, will be at least as fast as it was
14:31slashus2Point taken.
14:31slashus2Just experimenting
14:31rhickeyCounted implies constant-time, chunked seqs can't generally beCounted, though some specific ones can
14:32ChouserI thought writing a chunking 'iterate' might be fun.
14:33rhickeyChouser: you mentioned that before, one issue is the 'chunked' lazieness, might be ok for some usages but not others
14:33Chousermm... good point.
14:33rhickeydon't want to break those all important fib benchmarks :)
14:33Chouserheh
14:33Chousersame thing with 'repeat' I suppose.
14:34rhickeyrepeat can cache the thing
14:34rhickeynot really doing more work like iterate would
14:34Chousersorry, 'repeatedly'
14:34rhickeyah
14:35Chouser(repeatedly #(.readLine f))
14:36rhickeywe'll have to see what people want most with chunks in place, I know for me I care much more about not fully realizing intermediate results than I do never moving ahean more than one, what matters is that there be a recipe for those that want the latter
14:37rhickeythere will have to be a seq1, e.g. to stream singular values from something that would otherwise be chunked
14:37rhickeybut iterate1, repeatedly1... I don't know
14:38Chouserwell, repeatedly's specifically for side effects -- much more likely one extra step to be undesirable.
14:38Chousernot sure about iterate
14:39rhickeyalso there's no inherent indexed structure behind readLine, and I/O time is likely going to dominate seq overheads
14:40rhickeyas will any other non-trivial work
14:41rhickeythe chunked seqs most benefit the very lightweight work people often want to do with HOFs, but usually get penalized there vs loops
14:46rhickeyname of *flag* for controlling pre/post asserts? (when false turn into no code at all)
14:47Chouser*check-conditions*
14:47Chouser:-P nm.
14:48rhickeymatbe to toggle all assert?
14:48rhickeymaybe
15:17ctdeanIt's been a long while since I updated my clojure.jar. Is there a version of clojure-contrib that matches clojure_1.0.0 or should I just pull the bleeding edge for both?
15:18Chouserctdean: afaik, master contrib currently still works with clojure 1.0
15:19ctdeanIs that just svn update from my clojure-contrib dir? or is there a better place for me to download it?
15:20Chousercontrib and clojure have moved to git
15:20ctdeanaha, didn't know contrib had move also. Thanks so much
15:21Chouserhttp://github.com/richhickey/clojure-contrib/tree/master
15:21ctdeanPerfect, got it
15:23ctdeanAll that worked great.
15:25rhickeypre/post conditions are up - feedback welcome
15:30rhickey*assert* false nils-out asserts
15:30Chouser% as post arg
15:32Lau_of_DKHi everybody - I just want to let the people watching ClojureQL know that we're sorry that development has been so slow for the past 6 months - We are now up and running at full speed and have 2 working demos, 1 for MySql, 1 for Derby! We are now moving on to implementing JOINS, and that will but us at the very edge of version 1.0 :)
15:33ChouserLau_of_DK: great!
15:33rhickeyLau_of_DK: cool - link?
15:34kotarakhttp://github.com/Lau-of-DK/clojureql
15:34kotarakDon't look too closely. ;)
15:34Lau_of_DKhttp://github.com/Lau-of-DK/clojureql/tree/master
15:34Lau_of_DKoh :)
15:38Lau_of_DKSidenote: We are implementing dbms-specific routines in backend/derby.clj for example. If anybody would like to contribute patches for PostgreSql, Oracle, etc, it would be greatly appreciated :) We are currently targeting MySql and Derby exclusively.
15:47Jonathan-Smithare there any tutorials on how to properly structure/build a clojure project?
15:47Jonathan-Smithfor example if I have multiple source files with different name spaces, how do i tell clojure to load them in a certain order
15:49markcolYou can take a look Stuart Holloway's Lancet project that goes with the book "Programming Clojure". The sources are on github at http://github.com/stuarthalloway/lancet/tree/master
15:49ctdeanAlso the http://clojure.org/libs is reference page about this subject
15:52Jonathan-Smithcool, thanks
17:01bpattisonis there a function that returns a list of string delimited by line breaks? I tried (re-split #"\n" lines) but it throws away lines that only have a line break in them, i.e. empty string
17:02bpattisonI also tried (line-seq lines) but lines is a string and not a rdr
17:02Chousukeyou could wrap it in a StringReader
17:03kotarak,(with-in-str "a\nb\c\n" (line-seq *in*))
17:03clojurebotUnsupported escape character: \c
17:03kotarakpfff
17:04Lau_of_DKIs the Google Code SVN no longer updated, with the adoption of Git ?
17:04kotarak,(with-in-str "a\nb\nc\n" (line-seq *in*))
17:04clojurebotjava.lang.ClassCastException: clojure.lang.LineNumberingPushbackReader cannot be cast to java.io.BufferedReader
17:04kotarak-.-
17:06ctdeanYes, only github now
17:07rhickeysvn, what's that?
17:07hiredmanhar har har
17:07ctdean,(re-seq #".*\n?" "abc def\n123\n\n789")
17:07clojurebot("abc def\n" "123\n" "\n" "789" "")
17:07Chouserbpattison: re-split shouldn't throw away empty strings.
17:08Lau_of_DKCool :)
17:08Lau_of_DKrhickey: What changed your mind ?
17:08ctdeanAlmost right on the regex
17:09Chouserooh, instance is called "new"?
17:09Chouser,(re-split #"\n" "a\nb\nc\n\nd\n\ne")
17:09clojurebot("a" "b" "c" "" "d" "" "e")
17:09bpattison(re-split #"\n" "l1\nl2\nl3\n\n\n") ---> ("l1" "l2" "l3") instead of ("l1" "l2" "l3" "" "" "") -- but I haven't update my clojure environment for a while
17:09Chouser,(re-split #"\n" "a\nb\nc\n\nd\n\ne\n\n\n")
17:09clojurebot("a" "b" "c" "" "d" "" "e")
17:10rhickeyLau_of_DK: it wasn't a changeof mind, it was finding the answers to a set of questions: hosting the code (github), tools (IntelliJ git support is good), collab services I could use for Clojure and commercial work (assembla)
17:10Chouserhm, trailing empty lines are tossed.
17:10Lau_of_DKrhickey: I see
17:10ctdeanThat is the perl split behavior
17:11Chouserhuh. it seems rather unfortunate.
17:11bpattisonno worries, now I know how it works - I'll just work around it
17:11Chouser,(re-split #"_" "a_b_cd__ef___g___h_")
17:11clojurebot("a" "b" "cd" "" "ef" "" "" "g" "" "" "h")
17:12rhickeyChouser: not sure about new, will need to be able to distinguish (new Classname ...) from (new instancename [bases] ...)
17:12ctdeantry giving a limit, that might change it
17:12Lau_of_DKbtw, rhickey, thumbs up on the pre/post conditions, thats awesome
17:12rhickeyanyone try them yet? (pre/post)
17:12ctdean,(re-split #"_" "a_b_cd__ef___g___h_" -1)
17:12clojurebot("a" "b" "cd" "" "ef" "" "" "g" "" "" "h" "")
17:13bpattisonah! that worked
17:13ctdeanyep, it's java copying the perl behavior
17:13bpattisonworks perfect now -- thanks!
17:15itistodayrhickey: i was wondering if there was any way to improve closure's api docs?
17:15itistodayrhickey: I come from newLISP, and I'd like to get to know Clojure too, but its api docs are far less easy to navigate and are much less indepth
17:15rhickeyitistoday: improve how?
17:16itistodayrhickey: i.e. have functions grouped by area (string manipulation, list manipulation, file manipulation, etc)
17:17Chouser(defn re-split [p s] {:pre (instance? java.util.regex.Pattern p)} (seq (.split p s)))
17:17itistodayrhickey: this is how newLISP does it: http://www.newlisp.org/manual_frame.html
17:17Chouserthen this should fail, right? (re-split "_" "a_b__c___d_")
17:18rhickeyitistoday: newLisp has to implement a lot of fns Clojure doesn't, e.g. files, sockets etc
17:18rhickeybut what Clojure does implement is divided up along the left, with sections like http://clojure.org/sequences
17:18Chouserah, need another vector.
17:18rhickeythat have lists of sequence fns
17:19itistodayrhickey: ah, OK thanks I'll try to get used to that
17:19Chouserso this works: (defn re-split [p s] {:pre [(instance? java.util.regex.Pattern p)]} (seq (.split p s)))
17:20rhickeyitistoday: you'll also want to keep this handy: http://java.sun.com/j2se/1.5.0/docs/api/
17:20ctdeanitiistoday: If you have an idea for a different layout, you could write a program to generate it. All the api functions are self documenting
17:20ctdean,(doc subvec)
17:20clojurebot"([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."
17:21itistodayrhickey: yeah, thanks, I know of that from way back when I used to care about Java :-p (now it looks like I'll be getting back into it because of Clojure)
17:21Chouserrhickey: I don't yet understand why new-new has to be done before c-in-c
17:21itistodayctdean: thanks!
17:21hiredmanerm
17:21hiredmannew-new? I thought it was implement or whatever
17:22rhickeyhiredman: or whatever
17:22hiredman,or-whatever
17:22clojurebotjava.lang.Exception: Unable to resolve symbol: or-whatever in this context
17:24hiredmanwhatever is host in parens?
17:24rhickeyChouser: I'd like to have the final model in place, i.e. if we need classes with best perf we need Java right now, that doesn't make newnew a requirement, but I wanted to see what it would take
17:24rhickeywe could use interfaces + proxy and have minimal code to change - proxy->newnew
17:24clojurebotproxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.
17:25Chouserrhickey: ahh.. so if it turns out newnew isn't going to cut it, the work to make c-in-c hasn't been wasted yet.
17:25rhickey?
17:26Chouseraren't you saying that the reason to do newnew first is to prove it's a good model before rewriting it all in clojure?
17:27rhickeyno, newnew is a good model, I'd like to use it when writing c-in-c
17:27rhickeyI need newnew more than c-in-c right now, I still have to write classes or deal with perf issues, new range a case in point
17:27Chouseroh. yes, but I'd like to have c-in-c before trying to write newnew
17:28hiredmanhow metacircular
17:28Lau_of_DKI feel lost, what is this newnew and c-in-c, where do I go read ?
17:28rhickeyagreed, I'd like to write newnew in c-in-c, and I need it yesterday :)
17:28itistodayhow similar are clojure's sequences to SICP streams?
17:28ChouserLau_of_DK: http://www.assembla.com/wiki/show/clojure/New_new
17:28Lau_of_DKThanks
17:29Chouserc-in-c is just translating as much of clojure as possible from .java to .clj
17:29rhickeyitistoday: same idea, but they (Clojure's) are much more powerful
17:29itistodayrhickey: i see that clojure has the delay/force functions, but they're not mentioned on the sequences page, are they used internally by the sequences?
17:30ChouserLau_of_DK: my weak ugly and incomplete attempt at c-in-c: http://github.com/Chouser/clojure-compiler
17:30rhickeyClojure's seqs are defined in terms of interfaces, really a family of sequences, and are unified and interoperable with concrete seqs
17:30Lau_of_DKbtw, where's clojure-script at Chouser ?
17:30rhickeythe mechanism underneath is more involved then delay/force, but similar idea
17:30ChouserLau_of_DK: contrib
17:31rhickeybasically Clojure is full of production implementations of ideas you'll find in SICP
17:31Lau_of_DKChouser: I meant in terms of maturity
17:31ChouserLau_of_DK: but I have no intention of doing more work on clojurescript until c-in-c is done.
17:32itistodayrhickey: cool. still wondering about why delay/force is part of the api then, are they used somewhere else? or are they just there for the developer to use if they need to?
17:32rhickeyitistoday: they are just useful library functions
17:32clojurebotThey found no relationship between a programmer’s amount of experience and code quality or productivity.
17:33Chouserthe move from lazy-cons to lazy-seq left clojurescript behind, and the thought of what would be required to keep it synced up with chunks, newnew, etc. is just exhausting.
17:33itistodayrhickey: k, thanks
17:33rhickeyChouser: while a direct attempt at cinc is possible, I have a large list of things I want to do differently
17:33Lau_of_DKI know the feeling, we just climbed that hill with ClojureQL :)
17:34rhickeye.g. not use reflection and concrete class instances during compilation, requires abstracting out type info provision
17:34rhickeybut maybe there's a layered approach, I'll try to knock some of my notes into the wiki
17:36itistodayas Java is full of mutable objects, is there a document anywhere that discusses the considerations one should take if using it from a multi-threaded clojure program?
17:37itistodayor is at as simple as simply treating it as you would with java?
17:38Lau_of_DKrhickey: tried emacs' assembla-wiki-mode ?
17:39rhickeyitistoday: coarsely, use Clojure data structures and facilities for your models, use java for I/O
17:40itistodayrhickey: if that I/O though might be one that's accessed by multiple clojure threads at a time.. what do you do? can you just wrap it in a ref and then use sync on it?
17:42Chousukecan't do IO in transactions
17:42Chousukeyou could use agents
17:42itistodayChousuke: ah, so have an agent that's responsible for the IO?
17:42Chousukesomething like that.
17:42rhickeyitistoday: IO from multiple threads it outside the scope of Clojure, there are separate protocols for each IO library (swing event thread, sockets stuff, db connection pooling etc)
17:43itistodaythanks, i'll stop bugging you guys with questions now and do some more reading :-)
19:08JAS415does the -> operator only work for functions that are associated with a name?
19:09hiredmannope
19:09hiredmanbut it isn't as pretty
19:09hiredman,(-> "foo" (#(.toUpperCase %)))
19:09clojurebot"FOO"
19:09hiredmanyou just double up on the parens
19:09clojurebotΜΟΛΩΝ ΛΑΒΕ
19:10hiredmanclojurebot: what?
19:10clojurebotwhat is java
19:10JAS415oh you have to do an extra set of parens
19:46ozzileeCompojure seems to include the path my application is deployed at when matching routes. Does anyone know if that's intentional?
19:47ozzileei.e. if I deploy my app at "mysite.com/myapp", all of my routes have to start with "myapp/". Am I doing something wrong?
19:47grrrt"myapp" is your servlet's context path I assume
19:48grrrtif you don't want that, you could deploy the servlet under the ROOT context, but I'm not sure how to do that with compojure
19:50ozzileegrrrt: I can do that in tomcat, but I'd only be able to have one app per domain in the root context, correct?
19:51grrrtthat sounds plausible yes
19:52ctdeanDo you mean when using defserver? I'm not following.
19:53ozzileectdean: Using defroutes. (defroutes app (GET "*" (str (params :*)))).
19:53ozzilee(defservice app)
19:54ozzileeCompile that to a .war file, deploy it at context myapp, visit myapp/foo, and get "myapp/foo" in the response. To me, it should be just "foo".
19:55ctdeanI see. I've never put my stuff in a .war, so I have no idea.
19:56ctdeanThe plain vanilla (e.g. from a repl) doesn't prepend a path
19:58ozzileectdean: Yeah, it's only an issue when deploying in a servlet container.
19:59ctdeanTry the compojure mailing list, they're responsive
20:02ozzileectdean: I will eventually.
20:09Drakesonis it possible to insert break-points in function definitions in slime?
20:09Drakeson(e.g. the way you can C-u M-C-x a defun in elisp)
20:10grrrtDrakeson: I just tried that with cljdb - http://georgejahad.com/clojure/cljdb.html
20:10grrrtit did work
20:10Drakesonthanks
20:10grrrtno worries
20:17JAS415is it a common problem for clojure-dev to crash if repl output is too large?
20:17JAS415i keep having to force-quit eclipse it seems
20:38DrakesonDo you happen to know of a way to control firefox through java (and ultimately through a clojure repl)?
20:40hiredmanDrakeson: are you just looking to webbrowser programaticly?
20:40hiredmanhtmlunit works pretty well
20:40Drakesonhiredman: not just that.
20:41Drakesonthere is this javascript console (firebug) that is great. it would be even better if I could use a similar clojure repl to control and debug pages
20:53durka42there is mozrepl but i think that's javascript
20:54durka42but you don't use clojure to script pages (unless you're using clojurescript), so how would it be as useful as firebug?
20:55Drakesondurka42: if there was (or hopefully is) a way to interface to firefox through java, I could potentially have a clojure repl to do that instead.
21:00rhickey,(partition 3 1 nil (range 10))
21:00clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$partition
21:00rhickeyhrm, new partition does:
21:00rhickeyuser=> (partition 3 1 nil (range 10))
21:00rhickey((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9) (8 9))
21:03rhickeyseems to me partition with step 1 should never use the pad
21:03rhickeyuser=> (partition 3 1 [42] (range 10))
21:03rhickey((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) (6 7 8) (7 8 9) (8 9 42))
21:09Chouserit should include (9 42 42) as well?
21:10Chousershouldn't
21:10rhickeyno, once it has produced a partition containing the last element of the coll it should be done
21:11Chouserhm... yes
21:11Chouser(partition 3 2 nil (range 5)) should end with (2 3 4)
21:12rhickeyI've kicked https://www.assembla.com/spaces/clojure/tickets/120 back to Dimitry
21:22Drakeson~
21:22clojurebotwhat is java
21:22Drakeson~paste
21:22clojurebotlisppaste8, url
21:22lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
21:22lisppaste8Drakeson pasted "original partition" at http://paste.lisp.org/display/82474
21:23lisppaste8Drakeson annotated #82474 "modified" at http://paste.lisp.org/display/82474#1
21:26lisppaste8Drakeson annotated #82474 "better" at http://paste.lisp.org/display/82474#2
21:28Chouserif you use 'seq' as the opposite of 'empty?', then you can use if-let instead of repeating the drop expr
21:29Drakesonsorry, I didn't get it
21:30Drakesonwhich drop expression is repeated?
21:30Chouser(if-let [cont (seq (drop n s))] (cons p (partition n step pad cont)) (list (take n (concat p pad)))))
21:31Chouseroh
21:31Chousernm.
21:31Chouser:-) ignore me.
21:31Drakeson:p
21:32sethsI wish the api, special_forms, and kin pages on clojure.org were wiki pages
21:33Drakesonkin pages?
21:33sethsit's frustrating when things like nthrest are mentioned in multiple places but don't exist
21:33Drakesonhow is the web site managed? is it under git, by any chance?
21:34Chouserit's a wikispaces site
21:35sethsmust be private, wikispaces.com says this: Your search - Clojure - did not match any documents.
21:37Chouserseths: you're welcome to write up a list of errors and post it to the google group.
21:37sethsgood point
21:37Chouserit would be great if it were in git
21:38moc`Hi, sorry to interrupt. I am just starting out with Clojure and can't figure out why this code doesn't work: (map #(apply % '(1 2)) '(+ -)) => (2 2). I was expected (3 -1). Any ideas anyone?
21:41Chousermoc`: by quoting the list '(+ -) you're preventing the evaluation of each of those symbols
21:42Chouseryou wanted a list of 2 functions, but instead you have a list of 2 symbols.
21:42Chouserif you use [+ -] instead, each of those symbols will be evaluated, and you'll have a vector of functions.
21:42moc`Chouser: OK, I get it.
21:43Chouser,('+ 1 2)
21:43clojurebot2
21:43moc`Chouser: Thanks. It was doing my head in.
21:43Chouseryou're welcome. It's why we're here. :-)
21:47sethsok, Rich renamed nthrest to nthnext on Feb 17th 2009
21:48sethscommit b8e333fb3437dca760f16136ed074a4dd463fe35
21:48dreishExtra confusing because a symbol acts as a function in the same way that a keyword does, taking a map as its first arg, and an optional not-found value as its second.
21:48dreish(That should have been to moc`)
21:49dreishBut it doesn't throw an exception if the first arg isn't a map. It just returns the not-found value (or nil).
22:17Chouseranyone here used enlive on xml docs?
23:01JAS415gotta say
23:01JAS415i love memoization as a primitive
23:04Chouseranyone used enlive at all?
23:04grrrtyes I have
23:04grrrtjust for tagsoup though
23:04Chouserwell, that may still help me.
23:04grrrtI love the idea of enlive
23:05ChouserI just need a working example -- input html and 'select' call
23:05Chouserfor what I'm doing me zip-filter would be sufficient, but I suspect enlive is better in every way. ...I just can't figure it out.
23:05clojurebotfor is not used enough
23:05ChouserI've got my xml parsed into a format I think enlive wants.
23:06Chouserbut (enlive/select xml [:description]) returns an empty seq
23:06grrrtI'll rummage through my clojure snippets for a bit, I must have something there
23:06Chouserin fact, anything I put in place of [:description] returns an empty list.
23:07Chousereh, I but that means xml is in the wrong format.
23:07Chouserbet
23:08grrrtwhat format is it?
23:08grrrtI could just load a plain text file as a resource: (html-resource "templates/my-template.html")
23:09Chouseryeah, but I'm trying to avoid needing tagsoup, since I just need xml.
23:09Chouserif I were less stubborn this wouldn't be a problem
23:09grrrtah sure, I see
23:09Chouserxml is fron (xml/parse foo)
23:09grrrthm I think I have only ever used enlive's deftemplate macro
23:10Chouser(enlive/select (xml/parse input-stream) [:description])
23:12Chouserwoo! got it
23:13Chouser(enlive/select [(xml/parse input-stream)] [:description])
23:13grrrtah
23:28holmakHas anyone done much work with using Swing or another Java UI toolkit from Clojure?
23:28holmakMore importantly, has anyone found a way to make it a tolerable experience?
23:28grrrtI'm working on something that makes using SWT easier
23:28holmakMay I ask what approach you are taking?
23:29grrrtwell (it's a work in progress still)
23:29grrrtI have created an easy way to specify SWT widgets in a tree
23:29holmakaha
23:30holmak(I had given some thought to this problem as well.)
23:30grrrtyou can basically say things like (shell {:outlet :my-shell} (menu-bar (menu "File" (menu-item "New" {:shortcut \N})))) etc
23:30holmakI never realized how incredibly procedural Swing is until I used it from Clojure
23:30grrrtI know - I'm fighting SWT because everything has to happen in the UI thread
23:31holmakWell, I think that problem is tolerable if you just make a queue that you deposit UI calls into
23:31grrrtI have a separate namespace with functions that actually create the widgets
23:31holmakin Swing, there's SwingUtilities/invokeLater, of course
23:31grrrtthey do (in-ui (Shell. (display)))
23:31holmakhandy
23:32holmakSo, here is the tricky problem I have -- how do you handle events, and how do you handle changing state of widgets?
23:32grrrtSWT uses events like selection, keydown etc
23:32holmakI'm not familiar with SWT
23:33hiredmanhttp://gist.github.com/107140 <-- EDT macro is very useful
23:33grrrtI can respond to a menu selection by doing (menu "New" {:on-Selection (fn [evt] (println "Menu selected!"))})
23:33holmakSeems solid -- so how would you mutate widgets, like, to append to a text field?
23:33hiredmangenerally I have (future do stuff) in an event listener
23:33hiredman(to push stuff of EDT)
23:33hiredmanoff
23:34grrrtwell, the structure of widgets I mentioned earlier
23:34grrrtall widgets support an :outlet option, such as {:outlet :my-label} for some text label
23:35grrrtthe whole widget structure returns a map with all widgets that have an outlet defined
23:35grrrtif a button-push calls the "change-text" function, I can just do (.setText (:my-label *outlets*) "New Text")
23:36holmaknice
23:36grrrtbecause all UI stuff happens in the UI thread, this works, otherwise I could use agents (to go to other threads) or use in-ui
23:36grrrtWhen it's slightly more polished I'm planning to put my efforts online somewhere
23:37grrrt(I stole the term outlets from Mac OS X Cocoa)
23:37holmakIt certainly seems like the Clojure community would benefit from a nice declarative GUI library/wrapper
23:37grrrtyes, it's tricky to combine functional programming with a gui
23:37holmakYour approach is similar to the thoughts I had
23:37holmakI started out thinking about Django templates
23:37holmakor really, and web framework template, take your pick
23:38holmakwhere you have little slots that you can plug your content in
23:38grrrtyes indeed
23:38holmakBecause what I want to avoid above all else is keeping a big pile of widget objects around each with a dozen methods for mutating it
23:38holmakSorry, that was a bit of a run-on
23:38grrrt:) no worries
23:39holmakThe trick is that you don't want to recreate the GUI every update
23:39holmakunlike on teh web
23:39grrrtyeah, you need some kind of context to store your UI objects in
23:39holmakRight now I am doing horrific things with Swing in the name of getting another project done
23:40grrrtheh. I started out wanting to get a window going to do some graphics, then the "design the perfect world" syndrome kicked in
23:40holmakIdeally, you would have a pure Clojure data structure, like a map, that you could throw at your GUI "handle", and say, "update, GUI!"
23:40holmakand everything would drop into its slot
23:41grrrthm, that sounds interesting
23:41grrrtI don't see why you couldn't do that
23:41holmakEh, there has to be some kind of compromise between performance and declarativeness
23:41hiredmanoh god
23:41hiredmanforeclojure
23:41hiredman:|
23:41holmakIt's definitely an interesting problem
23:42holmakhiredman: where?
23:42hiredmanthe google group
23:42grrrtwow. just read the latest msg
23:43holmakhahaha
23:43holmakThat's both witty and terrible
23:43holmakIt's much harder to come up with good Clojure project names than, say, Python project names
23:43grrrtholmak: are you considering a situation where the UI is mostly updated in response to user actions?
23:44hiredman~Xiphojura
23:44clojurebot2009:Jan:29:16:03:17 <hiredman> I call Xiphojura
23:44grrrtor from a background process
23:44holmak"I'm making a spreadsheet, I'll call it, uhh, pySpreadsheet!"
23:45holmakgrrrt: I don't really know where I was going with that thought. I didn't have a chance to think about it much.
23:46holmakBut this entire thought process was triggered by trying to work with the Swing Tree widget.
23:46holmakWhich is, in fact, a suite of about a dozen classes and a real nightmare.
23:46hiredmanyou could have an agent with a watcher
23:47grrrthiredman: how does that work?
23:47holmakOh, very interesting -- use the watcher to trigger changes, instead of validating changes?
23:47hiredmanyou alter the map in the agent, and the watcher updates the gui state based on the new values in the map
23:49hiredmanwould make for an interesting toolkit design
23:49grrrthm. that sounds good
23:49holmakI should write these things down.
23:50grrrtneh just implement it
23:50holmakAbout the watchers, though: asynchronous madness!
23:50holmakIf only we had a language well suited to dealing with massive concurrency...
23:51hiredmanwell, updates will be serialized anyway
23:52hiredmanbecause the watcher will dump them on the edt
23:52holmakOh I know. It's just that I would never devise a system using three parallel threads of execution in any other language.
23:52holmakBut here, it practically makes sense!
23:53hiredmanwell, having gui stuff going on in multiple threads is a "dead dream" so you would need at least two threads anyway
23:53grrrthiredman: does Swing's invokeLater work with "nested" calls?
23:54grrrti.e. could you do (EDT (EDT (....)) ?
23:54holmakI feel like that would just invokeLater some invokeLaters
23:55grrrtmy SWT equivalent would block if I tried that.
23:55hiredmangrrrt: invokelater just ques up Runnables on swing's Executor
23:55grrrtah right
23:55holmakhooray queues
23:55hiredmanif EDT used invokeandwait or whatever it's called, then you would have a problem
23:55grrrtyeah
23:56holmakSo, how do you feel about SWT? Either of you? I'm using Swing because it was closer, but I'm open to conversion.
23:56grrrtI don't know much about swing, can't really compare
23:57grrrtSWT seems reasonably straightforward, but I'd hate to do it in java
23:57grrrt5 lines of code for a simple menu item...
23:57hiredmanswt is full of native code :(
23:57grrrttrue
23:59grrrtbut you can download or build it for many platforms
23:59hiredmanwould rather just depend on the jre