2009-06-24
| 03:27 | Lau_of_DK | Top of the morning gents |
| 03:27 | cgrand | morning Mr Lau! |
| 03:50 | frodef | so 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:51 | frodef | (mymethod [#^the-class arg] ...) seems not to be right? |
| 03:59 | hiredman | frodef: you don't |
| 03:59 | hoeck | frodef: proxy maps a clojure fn to each method-name, so you have to dispatch inside the fn |
| 03:59 | clojurebot | proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays. |
| 03:59 | hiredman | what you do is you put a cond or similar inside the method |
| 03:59 | frodef | ah, ok. So both methods in the interface maps to the same-named fn. Thanks. |
| 04:36 | frodef | how do I ask wheter a value implements a certain interface? |
| 04:36 | frodef | (or is of a certain class?) |
| 04:36 | frodef | ah, instance? |
| 04:37 | frodef | ..for classes, but not interfaces. |
| 04:38 | frodef | urgh, for interfaces too. I got the argument ordering wrong. sorry about the noise. |
| 06:33 | frodef | how do I round a number to nearest integer? e.g. (round 10 3) -> 3 |
| 06:33 | frodef | ..or (round (/ 10 3)) -> 3 |
| 06:35 | sunwukong | round found in clojure.contrib.math works like your second example |
| 06:37 | frodef | ok, thanks. |
| 06:43 | AWizzArd | General 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:45 | sunwukong | imho legally: yes ; morally: depending on the actual server/amount of data |
| 06:45 | dhaya | AWizzArd: 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:55 | AWizzArd | ah good, the robots.txt should help, thanks you two |
| 08:36 | rhickey | sweet, this is what's nice about being on the JVM. Had updated my os x java vm, now includes VisualVM... |
| 08:37 | rhickey | so 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:40 | rhickey | not as powerful as yourkit, but handy |
| 09:02 | Chouser | rhickey: I think you have enough earnings from Clojure T-shirts to offer a bounty for contrib.jar |
| 09:02 | rhickey | Chouser: heh, now I need to bribe, eh? |
| 09:03 | mblinn | well you could pay in t shirts |
| 09:03 | Chouser | bah, a couple dollars short, at least for some shirts. |
| 09:03 | Chouser | rhickey: just making you aware of your options. :-) |
| 09:04 | rhickey | thanks |
| 09:04 | Chouser | ah, it looks like any white T would be covered. |
| 09:06 | rhickey | hmm, I see "What would it take?" implies a bribe possibly |
| 09:07 | rhickey | Have been working on pre/post conditions |
| 09:07 | Chouser | cool |
| 09:09 | rhickey | something like: |
| 09:09 | rhickey | (defn foo |
| 09:09 | rhickey | #^{:pre [(even? x) (< x y)] :post [(not (nil? _))]} |
| 09:09 | rhickey | [x y] ...) |
| 09:09 | rhickey | eventually some mojo to make that: |
| 09:09 | rhickey | (defn foo |
| 09:09 | rhickey | [x y] |
| 09:09 | rhickey | {:pre [(even? x) (< x y)] :post [(not (nil? _))]} |
| 09:09 | rhickey | ...) |
| 09:10 | rhickey | but still yielding the map as metadata on the arglist |
| 09:10 | Chouser | I'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:10 | rhickey | thus tools could find and display via metadata |
| 09:11 | rhickey | Chouser: that's one idea, built on some type of built-in logic lang like datalog/prolog |
| 09:11 | Chouser | yeah, ok. That was my impression. |
| 09:11 | rhickey | would be a hybrid of checker and analysis tool |
| 09:12 | rhickey | one point on the post conditions is how to label the return value (_ above) |
| 09:12 | Chouser | runtime pre/post is good too of course. Do you imagine it being used mainly during testing and turned off during production? |
| 09:12 | rhickey | options are _, or the fn name (would require it be named) |
| 09:13 | rhickey | Chouser: that depends on the app, so there will have to be some flags |
| 09:13 | Chouser | _ elsewhere has come to mean "I don't care" ... might be pretty confusing to overload that meaning here. |
| 09:13 | rhickey | considered assert no/yes/condiionally (supply a var) |
| 09:14 | rhickey | Chouser: agreed, _ means don't care everywhere else |
| 09:14 | achim | how about making % readable outside #(...) for such things (similar to unquote)? |
| 09:14 | rhickey | could use a fixed name, like 'ret' |
| 09:14 | rhickey | achim: I have though about that |
| 09:14 | Chouser | achim: I was wondering that too |
| 09:15 | rhickey | one 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:16 | rhickey | right now when you see % you know you are in an anonymous fn def |
| 09:16 | Chouser | people can already do (binding [map filter] ...) Just because it's bad doesn't mean it has to be forbidden. |
| 09:16 | rhickey | agreed |
| 09:17 | rhickey | one other point was possible destructuring of return value for post |
| 09:17 | Chouser | hmmm |
| 09:17 | rhickey | else :post [(let [[x y] %] ...)] |
| 09:18 | rhickey | ok if only one test, tedious if more |
| 09:19 | Chouser | right, but giving a spot in which to name the rtn value would solve both the naming and destructuring at once. |
| 09:19 | rhickey | Chouser: that's something different altogether, seems like a hassle |
| 09:19 | Chouser | :rtn rtn :post [(< 5 rtn 10)] |
| 09:20 | rhickey | I don't like it separate from post |
| 09:20 | Chouser | yeah, that was to avoid :post [rtn (< 5 rtn 10)] |
| 09:20 | rhickey | exactly |
| 09:21 | rhickey | but :post [aname ...] is the best I could come up with, just irregular |
| 09:23 | rhickey | either name is always required, or must be a symbol/vec/map binding form |
| 09:23 | rhickey | will work until we have lists as destructuring forms :) |
| 09:26 | Chouser | I 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:26 | rhickey | agreed, not done anywhere else |
| 09:27 | lpetit | why not a short and a long form ? |
| 09:27 | Chouser | [:pre (< 5 x) (even? x) :post [rtn] (< 5 rtn 10) (odd? rtn)] |
| 09:27 | Chouser | eh. |
| 09:27 | achim | might 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:28 | rhickey | achim: no |
| 09:28 | Chouser | I 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:28 | lpetit | short form takes directly a vector of forms |
| 09:28 | lpetit | long form takes a map with :rtn (taking possibly a binding) , :tests (or something else) taking the vector of forms |
| 09:29 | rhickey | Chouser: plus the result is still a to-be-parsed bag |
| 09:29 | Chouser | not much point if the long form is longer than (let [[x y] %] (and ...)) |
| 09:29 | rhickey | lpetit: I'd really like to avoid that kind of thing. ns/require/use are the most complicated parts of Clojure for that reason |
| 09:30 | lpetit | rhickey: I understand |
| 09:30 | Chouser | now's not the time to discuss, but I'd love to require removed and 'use' simplified. I think it can be done. |
| 09:32 | lpetit | having the output follow a given "destructuring form" may convey enough information on itself to deserve not being mixed with other post conditions. |
| 09:33 | frodef | is there some variable somewhere that limits the size of stacktrace that gets printed? |
| 09:33 | rhickey | I'm going to work on the presumption that multi-test postconditions requiring destructuring will be rare |
| 09:33 | frodef | I have a stack overflow that I find it hard to find the source of. |
| 09:34 | Chouser | frodef: you might look at clojure.contrib.stacktrace |
| 09:35 | lpetit | So maybe having along with :pre and :post some :rtn-struct (I'm really bad at naming things :-(. |
| 09:35 | lpetit | If 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:35 | lpetit | If :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:35 | clojurebot | http://clojure.org/data_structures#toc10 |
| 09:36 | frodef | Chouser: ok, thansk |
| 09:38 | lpetit | so the simple case : :post [(pos? %)] |
| 09:38 | lpetit | the moderate complex case :ret-struct [k v] :post [(not (nil? k)) (not (nil? v))] |
| 09:38 | lpetit | note 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:39 | lpetit | In the same time, the post condition code serves as documentation .... |
| 09:40 | Chouser | lpetit: 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:42 | frodef | hm.. these lazy lists are no fun debugging, are they.. :) |
| 09:43 | Chouser | frodef: can be a bit tricky. if you can handle a dorun temporarily, that sometimes helps. |
| 09:44 | lpetit | Chouser: 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:44 | frodef | Chouser: doall should do the same, no? |
| 09:45 | lpetit | But maybe it is too early and overlapping with the general problem of how to optionally expose type information |
| 09:45 | Chouser | frodef: 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:46 | Chouser | lpetit: except it's so nicely symmetric with input args. |
| 09:51 | weissj | what is the clojure equivalent of mapcar? |
| 09:52 | Chouser | weissj: I think just 'map' |
| 09:52 | lpetit | Chouser: yes, indeed. So you like the idea ? |
| 09:53 | Chouser | lpetit: 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:55 | Chouser | (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:55 | lpetit | :returns ret-name :post [(pos? ret-name) (even? ret-name)] |
| 09:55 | lpetit | or :returns [key val] :post [(not (nil? key)) (pos? val)] |
| 09:55 | lpetit | inserted in the map along with :pre , :docstring ... keys |
| 09:56 | Chouser | lpetit: I don't think that's terribly, but rhickey already said he didn't like it separated from the :post exprs. |
| 09:56 | Chouser | terrible |
| 09:58 | lpetit | (defn foo #^{ :pre [(even? x) (< x y)] :returns [k v] :post [(not (nil? k)) (> v y)] } [x y] ...) |
| 09:59 | lpetit | Chouser: well, the args names are separated from the :pre, and that seems not to be a problem, though :-) |
| 09:59 | Drakeson | assume (f l) -> [l1 l2] |
| 09:59 | Drakeson | how 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:59 | lpetit | ,(doc partition) |
| 09:59 | clojurebot | "([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:00 | lpetit | oh no |
| 10:00 | Chouser | Drakeson: example? |
| 10:01 | Chouser | I don't really understand what are in l1 and l2 |
| 10:01 | lpetit | ,(doc split-with) |
| 10:01 | clojurebot | "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]" |
| 10:03 | Drakeson | assume I call it partition-with. (partition-with #(split-at 3 %) (range 1 10)) -> [(1 2 3) (4 5 6) (7 8 9)] |
| 10:05 | Chouser | ahh |
| 10:06 | Chouser | returning a vector means non-lazy, so it can be built on reduce |
| 10:06 | frodef | increasing 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:07 | Drakeson | Chouser: laziness > vector, assume it returns a list then. |
| 10:13 | Drakeson | ,lisppaste |
| 10:13 | clojurebot | java.lang.Exception: Unable to resolve symbol: lisppaste in this context |
| 10:13 | Chouser | ,url |
| 10:13 | clojurebot | java.lang.Exception: Unable to resolve symbol: url in this context |
| 10:13 | Drakeson | ~paste |
| 10:13 | clojurebot | lisppaste8, url |
| 10:13 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 10:14 | lisppaste8 | Drakeson pasted "partition-with" at http://paste.lisp.org/display/82424 |
| 10:14 | Drakeson | now, that is not equal to some other function we already have, right? |
| 10:16 | Chouser | Drakeson: I don't think so. |
| 10:16 | Drakeson | thanks |
| 10:16 | Chouser | for some cases, contrib.seq-utils/partition-by might suffice, but it's doing something a bit different. |
| 10:17 | Drakeson | I stole it from partition-by |
| 10:17 | Chouser | oh, ok. |
| 10:17 | Drakeson | (modified it a bit) |
| 10:17 | Drakeson | btw, I need that function for parsing. |
| 10:18 | Chouser | I think partition-by could be written using split-with and your partition-with |
| 10:32 | lpetit | http://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:32 | lpetit | ...problem ? |
| 10:39 | lpetit | ? |
| 11:45 | rhickey | Drakeson: that code is not fully lazy |
| 11:46 | Chouser | btw, someone pointed out that reduce on range is slower in chunked than master. |
| 11:47 | Chouser | I had to chain 2 or 3 more chunked operations before the chunking was a win over the Range object. |
| 11:47 | rhickey | Chouser: 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:47 | Chouser | right |
| 11:48 | tsdh | Hi. I'm currently transforming some clojure code into an eclipse projects to make it appealing to my colleagues. |
| 11:48 | rhickey | just 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:49 | tsdh | In 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:50 | tsdh | (ClassLoader/getSystemRosource "icons/a.png") returns nil. Adding several ../ in front doesn't make it happy, either. |
| 11:50 | Drakeson | how would you serialize an object into a file? would you use spit and pr-str ? |
| 11:51 | stuartsierra | Drakeson: yes, or open a writer and use pr |
| 11:52 | Drakeson | how would you get rid of *print-level* and *print-length* temporarily? |
| 11:52 | Drakeson | ,*print-level* |
| 11:52 | clojurebot | 30 |
| 11:52 | stuartsierra | (binding [*print-level* nil, *print-length* nil] ...) |
| 11:52 | tsdh | I think in Java I would use getClass().getResource(relativePathFromThis), but that has no equivalent in clojure, afaikt. |
| 11:52 | Drakeson | aaah, that's it, thanks. |
| 11:55 | tsdh | Oh, using simply (ImageIcon. "icons/a.png") works. Well, most often the simplest solution is still the best. |
| 11:55 | tsdh | ;-) |
| 12:09 | baetis-fly | Can anyone explain when you'd want to use definline? |
| 12:09 | opqdonut | for performance reasons i guess |
| 12:10 | Chouser | if 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:11 | baetis-fly | Let 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:12 | Chouser | baetis-fly: link to that code? |
| 12:13 | baetis-fly | Chouser: sure, one sec. |
| 12:14 | baetis-fly | http://github.com/lrenn/compojure/blob/4a2079d1a28cddcb174c4a7f650c6a70e3258f31/src/compojure/http/servlet.clj |
| 12:16 | baetis-fly | It'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:18 | Chouser | I'm not sure why that's not a macro. Clearly there's something I'm not getting here. |
| 12:19 | baetis-fly | Chouser: 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:34 | combasa | morning |
| 12:35 | rhickey | what'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:36 | rhickey | last time I had to delete local after push, then branch --track, seems wrong |
| 12:36 | Chouser | rhickey: you mean you want plain "git push" and "git pull" to operate on that branch? |
| 12:37 | rhickey | when in that branch locally, yeah |
| 12:37 | rhickey | that's how chunks is working |
| 12:37 | Chouser | oh, I see. I'm still learning how to use git against a git remote (instead of svn remote) |
| 12:37 | combasa | I wish I knew more about git, im just learning |
| 12:38 | Chouser | I've edited .git/config manually before, but I bet that's not right. |
| 12:38 | Chouser | or rather that there's something better. |
| 12:38 | Chousuke | use git config :P |
| 12:39 | rhickey | for chunks I did git push origin chunks, git branch -d chunks, git branch --track chunks origin/chunks |
| 12:39 | Chousuke | basically, you need to set configure branch.<name>.remote and branch.<name>.merge |
| 12:39 | rhickey | couldn't find a way to push with tracking |
| 12:40 | Chousuke | so git config branch.chunks.remote origin; git config branch.chunks.merge chunks |
| 12:40 | rhickey | Chousuke: I understand, but, ugh |
| 12:40 | Chousuke | actually, if the remote is origin, the first config is unnecessary |
| 12:42 | rhickey | this recipe seems oriented towards knowing you want a remote branch up front: |
| 12:42 | rhickey | git push origin master:refs/heads/some_branch |
| 12:42 | rhickey | git fetch origin |
| 12:42 | rhickey | git branch −−track some_branch origin/some_branch |
| 12:42 | rhickey | git checkout some_branch |
| 12:46 | Chousuke | git checkout -b branch origin/branch sets up tracking by default |
| 12:46 | Chousuke | hmm |
| 12:47 | rhickey | Chousuke: that's not the scenario |
| 12:47 | combasa | ya 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:47 | rhickey | local branch exists, want to create on remote with tracking |
| 12:47 | Chousuke | well, for that you'd need the two git config commands. |
| 12:48 | Chousuke | then just push |
| 12:48 | rhickey | using commands, not config file editing |
| 12:48 | rhickey | Chousuke: I get the config file method |
| 12:48 | Chousuke | as I said earlier, just: git config branch.chunks.remote origin && git config branch.chunks.merge chunks |
| 12:48 | Chousuke | could probably make an alias for that. |
| 12:49 | combasa | haven'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:52 | combasa | I'm going to have to re-read `git help branch` again I see |
| 12:53 | Chousuke | you can't really have a branch in a different directory other than by cloning |
| 12:54 | Chousuke | but clones of local repositories are cheap, as git just uses hardlinks whenever it can |
| 12:55 | combasa | yeah I realised it was a dumb idea :P |
| 12:56 | combasa | actually 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:56 | Chousuke | which part of the source? |
| 12:56 | combasa | yes which part |
| 12:56 | Chousuke | I mean, the java or the clojure side? :) |
| 12:56 | Chousuke | core.clj is pretty easy to understand. |
| 12:57 | Chousuke | the java stuff... not quite. :P |
| 12:57 | combasa | I'll have a look there then |
| 12:57 | combasa | where would be a good java place to start? |
| 12:58 | Chousuke | I haven't looked at it much :) |
| 12:58 | Chousuke | I guess it depends on what you want to know. |
| 12:59 | combasa | is the goal to have it all done in clojure at some point? |
| 12:59 | Chousuke | well, most, anyway |
| 12:59 | Chousuke | but that's probably not going to happen very soon :/ |
| 12:59 | combasa | well I don't think it really matters either way does it |
| 13:01 | Chousuke | hmm, interesting |
| 13:01 | Chousuke | there's a Seqable.java~be56ab81e88f8001494058a055089e982595c453 in my clojure source tree. in src/jvm/lang :P |
| 13:01 | Chousuke | looks like it's untracked. |
| 13:07 | amunite | hi 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:08 | combasa | do makes use .bashrc files? im on linux |
| 13:08 | combasa | mac's I mean |
| 13:09 | kotarak | When you use bash... then "yes" I suppos. |
| 13:09 | combasa | I see, maybe I'll just have a look at the guide first |
| 13:09 | Chousuke | by default, Terminal.app uses login as the shell, so it uses .profile |
| 13:09 | Chousuke | but if you use bash then bashrc will matter too. |
| 13:13 | combasa | hmm that guide smells a little funny to me |
| 13:16 | technomancy | it's pretty old |
| 13:16 | technomancy | well, sort of old. |
| 13:17 | technomancy | I guess the move to git is recent enough not to call it old. =) |
| 13:26 | Jomyoot | Is there a web framework for clojure? |
| 13:27 | combasa | I believe enclojure is a web framwork, but I haven't looked at it yet |
| 13:27 | slashus2 | ~compojure |
| 13:27 | clojurebot | compojure is http://github.com/weavejester/compojure/tree/master |
| 13:28 | slashus2 | ~ring |
| 13:28 | clojurebot | ring is http://github.com/mmcgrana/ring/tree/master |
| 13:28 | combasa | ah right, compojure |
| 13:28 | Jomyoot | anything close to rails? |
| 13:28 | combasa | whats enclojure? |
| 13:28 | slashus2 | A netbeans plugin for clojure. |
| 13:28 | combasa | ah right |
| 13:28 | Jomyoot | how is performance of enclojure vs. scala? |
| 13:44 | slashus2 | Could count be made chunk aware? |
| 13:58 | quidnunc | cgrand: Can you give me an example of how to use the text-node selector? |
| 14:00 | cgrand | quidnunc: at last :-) |
| 14:02 | cgrand | (select nodes [:abbr :> text-node]) should return a seq of string |
| 14:03 | quidnunc | cgrand: Sorry, different time zone + work makes it hard for me to catch up with you. |
| 14:04 | cgrand | and I'm sorry that today I have to run pretty soon |
| 14:04 | quidnunc | cgrand: Me too :) |
| 14:04 | cgrand | quidnunc: mail me |
| 14:05 | quidnunc | cgrand: :abbr is a placeholder for a tag name? |
| 14:05 | cgrand | yup but it's also a real tag-name |
| 14:05 | cgrand | have to go |
| 14:05 | quidnunc | cgrand: Thanks |
| 14:09 | lisppaste8 | slashus2 pasted "chunk count" at http://paste.lisp.org/display/82446 |
| 14:09 | slashus2 | What do you all think of this? |
| 14:13 | slashus2 | There are probably some improvements that could be made to the code, but you get the idea. |
| 14:14 | cemerick | wow, almost a 2x speedup. |
| 14:14 | slashus2 | yup |
| 14:14 | cemerick | should I expect the chunked stuff to make all seq operations faster in general (map, filter, etc)? |
| 14:14 | slashus2 | Range has taken a pretty significant performance hit from generating a chunked seq though. |
| 14:14 | Chouser | (count (range ...)) is constant time on master |
| 14:16 | slashus2 | Chouser: I looked at the code in RT and it looked like it incremented a counter. |
| 14:16 | Chouser | slashus2: what you've got seems reasonable. I wonder if chunk producers other than range would see much benefit. |
| 14:17 | slashus2 | Chouser: I guess range's performance will increase later.. |
| 14:18 | Chouser | slashus2: RT.count uses a counter if the collection is not Counted. |
| 14:18 | Chouser | If it's Counted, it asks the object to count itself -- for things like vectors and Range, this is constant time. |
| 14:20 | slashus2 | I see. |
| 14:20 | slashus2 | I guess we could also make chunks Counted... |
| 14:21 | Chouser | but on the chunked branch, range does not use Range, so your chunk-count has benefit there. |
| 14:24 | Chouser | (let [v (vec (range 1e6))] (time (chunk-count v))) |
| 14:24 | Chouser | it's interesting to compare that with core/count. |
| 14:25 | Chouser | oh, nm |
| 14:25 | Chouser | that's just showing that chunk-count should check for 'counted?'. |
| 14:26 | Chouser | (time (chunk-count (map identity (range 1e6)))) |
| 14:26 | Chouser | I think that's closer to what I meant to test. Looks like chunk-count still helps quite a bit. |
| 14:27 | Chouser | slashus2: I think rhickey is accepting chunked versions of seq-processing functions. |
| 14:30 | rhickey | slashus2: counting non-counted things is a waste, making faster not that important |
| 14:31 | rhickey | slashus2: range is work in progress, will be at least as fast as it was |
| 14:31 | slashus2 | Point taken. |
| 14:31 | slashus2 | Just experimenting |
| 14:31 | rhickey | Counted implies constant-time, chunked seqs can't generally beCounted, though some specific ones can |
| 14:32 | Chouser | I thought writing a chunking 'iterate' might be fun. |
| 14:33 | rhickey | Chouser: you mentioned that before, one issue is the 'chunked' lazieness, might be ok for some usages but not others |
| 14:33 | Chouser | mm... good point. |
| 14:33 | rhickey | don't want to break those all important fib benchmarks :) |
| 14:33 | Chouser | heh |
| 14:33 | Chouser | same thing with 'repeat' I suppose. |
| 14:34 | rhickey | repeat can cache the thing |
| 14:34 | rhickey | not really doing more work like iterate would |
| 14:34 | Chouser | sorry, 'repeatedly' |
| 14:34 | rhickey | ah |
| 14:35 | Chouser | (repeatedly #(.readLine f)) |
| 14:36 | rhickey | we'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:37 | rhickey | there will have to be a seq1, e.g. to stream singular values from something that would otherwise be chunked |
| 14:37 | rhickey | but iterate1, repeatedly1... I don't know |
| 14:38 | Chouser | well, repeatedly's specifically for side effects -- much more likely one extra step to be undesirable. |
| 14:38 | Chouser | not sure about iterate |
| 14:39 | rhickey | also there's no inherent indexed structure behind readLine, and I/O time is likely going to dominate seq overheads |
| 14:40 | rhickey | as will any other non-trivial work |
| 14:41 | rhickey | the chunked seqs most benefit the very lightweight work people often want to do with HOFs, but usually get penalized there vs loops |
| 14:46 | rhickey | name of *flag* for controlling pre/post asserts? (when false turn into no code at all) |
| 14:47 | Chouser | *check-conditions* |
| 14:47 | Chouser | :-P nm. |
| 14:48 | rhickey | matbe to toggle all assert? |
| 14:48 | rhickey | maybe |
| 15:17 | ctdean | It'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:18 | Chouser | ctdean: afaik, master contrib currently still works with clojure 1.0 |
| 15:19 | ctdean | Is that just svn update from my clojure-contrib dir? or is there a better place for me to download it? |
| 15:20 | Chouser | contrib and clojure have moved to git |
| 15:20 | ctdean | aha, didn't know contrib had move also. Thanks so much |
| 15:21 | Chouser | http://github.com/richhickey/clojure-contrib/tree/master |
| 15:21 | ctdean | Perfect, got it |
| 15:23 | ctdean | All that worked great. |
| 15:25 | rhickey | pre/post conditions are up - feedback welcome |
| 15:30 | rhickey | *assert* false nils-out asserts |
| 15:30 | Chouser | % as post arg |
| 15:32 | Lau_of_DK | Hi 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:33 | Chouser | Lau_of_DK: great! |
| 15:33 | rhickey | Lau_of_DK: cool - link? |
| 15:34 | kotarak | http://github.com/Lau-of-DK/clojureql |
| 15:34 | kotarak | Don't look too closely. ;) |
| 15:34 | Lau_of_DK | http://github.com/Lau-of-DK/clojureql/tree/master |
| 15:34 | Lau_of_DK | oh :) |
| 15:38 | Lau_of_DK | Sidenote: 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:47 | Jonathan-Smith | are there any tutorials on how to properly structure/build a clojure project? |
| 15:47 | Jonathan-Smith | for example if I have multiple source files with different name spaces, how do i tell clojure to load them in a certain order |
| 15:49 | markcol | You 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:49 | ctdean | Also the http://clojure.org/libs is reference page about this subject |
| 15:52 | Jonathan-Smith | cool, thanks |
| 17:01 | bpattison | is 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:02 | bpattison | I also tried (line-seq lines) but lines is a string and not a rdr |
| 17:02 | Chousuke | you could wrap it in a StringReader |
| 17:03 | kotarak | ,(with-in-str "a\nb\c\n" (line-seq *in*)) |
| 17:03 | clojurebot | Unsupported escape character: \c |
| 17:03 | kotarak | pfff |
| 17:04 | Lau_of_DK | Is the Google Code SVN no longer updated, with the adoption of Git ? |
| 17:04 | kotarak | ,(with-in-str "a\nb\nc\n" (line-seq *in*)) |
| 17:04 | clojurebot | java.lang.ClassCastException: clojure.lang.LineNumberingPushbackReader cannot be cast to java.io.BufferedReader |
| 17:04 | kotarak | -.- |
| 17:06 | ctdean | Yes, only github now |
| 17:07 | rhickey | svn, what's that? |
| 17:07 | hiredman | har har har |
| 17:07 | ctdean | ,(re-seq #".*\n?" "abc def\n123\n\n789") |
| 17:07 | clojurebot | ("abc def\n" "123\n" "\n" "789" "") |
| 17:07 | Chouser | bpattison: re-split shouldn't throw away empty strings. |
| 17:08 | Lau_of_DK | Cool :) |
| 17:08 | Lau_of_DK | rhickey: What changed your mind ? |
| 17:08 | ctdean | Almost right on the regex |
| 17:09 | Chouser | ooh, instance is called "new"? |
| 17:09 | Chouser | ,(re-split #"\n" "a\nb\nc\n\nd\n\ne") |
| 17:09 | clojurebot | ("a" "b" "c" "" "d" "" "e") |
| 17:09 | bpattison | (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:09 | Chouser | ,(re-split #"\n" "a\nb\nc\n\nd\n\ne\n\n\n") |
| 17:09 | clojurebot | ("a" "b" "c" "" "d" "" "e") |
| 17:10 | rhickey | Lau_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:10 | Chouser | hm, trailing empty lines are tossed. |
| 17:10 | Lau_of_DK | rhickey: I see |
| 17:10 | ctdean | That is the perl split behavior |
| 17:11 | Chouser | huh. it seems rather unfortunate. |
| 17:11 | bpattison | no worries, now I know how it works - I'll just work around it |
| 17:11 | Chouser | ,(re-split #"_" "a_b_cd__ef___g___h_") |
| 17:11 | clojurebot | ("a" "b" "cd" "" "ef" "" "" "g" "" "" "h") |
| 17:12 | rhickey | Chouser: not sure about new, will need to be able to distinguish (new Classname ...) from (new instancename [bases] ...) |
| 17:12 | ctdean | try giving a limit, that might change it |
| 17:12 | Lau_of_DK | btw, rhickey, thumbs up on the pre/post conditions, thats awesome |
| 17:12 | rhickey | anyone try them yet? (pre/post) |
| 17:12 | ctdean | ,(re-split #"_" "a_b_cd__ef___g___h_" -1) |
| 17:12 | clojurebot | ("a" "b" "cd" "" "ef" "" "" "g" "" "" "h" "") |
| 17:13 | bpattison | ah! that worked |
| 17:13 | ctdean | yep, it's java copying the perl behavior |
| 17:13 | bpattison | works perfect now -- thanks! |
| 17:15 | itistoday | rhickey: i was wondering if there was any way to improve closure's api docs? |
| 17:15 | itistoday | rhickey: 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:15 | rhickey | itistoday: improve how? |
| 17:16 | itistoday | rhickey: i.e. have functions grouped by area (string manipulation, list manipulation, file manipulation, etc) |
| 17:17 | Chouser | (defn re-split [p s] {:pre (instance? java.util.regex.Pattern p)} (seq (.split p s))) |
| 17:17 | itistoday | rhickey: this is how newLISP does it: http://www.newlisp.org/manual_frame.html |
| 17:17 | Chouser | then this should fail, right? (re-split "_" "a_b__c___d_") |
| 17:18 | rhickey | itistoday: newLisp has to implement a lot of fns Clojure doesn't, e.g. files, sockets etc |
| 17:18 | rhickey | but what Clojure does implement is divided up along the left, with sections like http://clojure.org/sequences |
| 17:18 | Chouser | ah, need another vector. |
| 17:18 | rhickey | that have lists of sequence fns |
| 17:19 | itistoday | rhickey: ah, OK thanks I'll try to get used to that |
| 17:19 | Chouser | so this works: (defn re-split [p s] {:pre [(instance? java.util.regex.Pattern p)]} (seq (.split p s))) |
| 17:20 | rhickey | itistoday: you'll also want to keep this handy: http://java.sun.com/j2se/1.5.0/docs/api/ |
| 17:20 | ctdean | itiistoday: 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:20 | ctdean | ,(doc subvec) |
| 17:20 | clojurebot | "([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:21 | itistoday | rhickey: 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:21 | Chouser | rhickey: I don't yet understand why new-new has to be done before c-in-c |
| 17:21 | itistoday | ctdean: thanks! |
| 17:21 | hiredman | erm |
| 17:21 | hiredman | new-new? I thought it was implement or whatever |
| 17:22 | rhickey | hiredman: or whatever |
| 17:22 | hiredman | ,or-whatever |
| 17:22 | clojurebot | java.lang.Exception: Unable to resolve symbol: or-whatever in this context |
| 17:24 | hiredman | whatever is host in parens? |
| 17:24 | rhickey | Chouser: 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:24 | rhickey | we could use interfaces + proxy and have minimal code to change - proxy->newnew |
| 17:24 | clojurebot | proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays. |
| 17:25 | Chouser | rhickey: 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:25 | rhickey | ? |
| 17:26 | Chouser | aren'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:27 | rhickey | no, newnew is a good model, I'd like to use it when writing c-in-c |
| 17:27 | rhickey | I 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:27 | Chouser | oh. yes, but I'd like to have c-in-c before trying to write newnew |
| 17:28 | hiredman | how metacircular |
| 17:28 | Lau_of_DK | I feel lost, what is this newnew and c-in-c, where do I go read ? |
| 17:28 | rhickey | agreed, I'd like to write newnew in c-in-c, and I need it yesterday :) |
| 17:28 | itistoday | how similar are clojure's sequences to SICP streams? |
| 17:28 | Chouser | Lau_of_DK: http://www.assembla.com/wiki/show/clojure/New_new |
| 17:28 | Lau_of_DK | Thanks |
| 17:29 | Chouser | c-in-c is just translating as much of clojure as possible from .java to .clj |
| 17:29 | rhickey | itistoday: same idea, but they (Clojure's) are much more powerful |
| 17:29 | itistoday | rhickey: 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:30 | Chouser | Lau_of_DK: my weak ugly and incomplete attempt at c-in-c: http://github.com/Chouser/clojure-compiler |
| 17:30 | rhickey | Clojure's seqs are defined in terms of interfaces, really a family of sequences, and are unified and interoperable with concrete seqs |
| 17:30 | Lau_of_DK | btw, where's clojure-script at Chouser ? |
| 17:30 | rhickey | the mechanism underneath is more involved then delay/force, but similar idea |
| 17:30 | Chouser | Lau_of_DK: contrib |
| 17:31 | rhickey | basically Clojure is full of production implementations of ideas you'll find in SICP |
| 17:31 | Lau_of_DK | Chouser: I meant in terms of maturity |
| 17:31 | Chouser | Lau_of_DK: but I have no intention of doing more work on clojurescript until c-in-c is done. |
| 17:32 | itistoday | rhickey: 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:32 | rhickey | itistoday: they are just useful library functions |
| 17:32 | clojurebot | They found no relationship between a programmer’s amount of experience and code quality or productivity. |
| 17:33 | Chouser | the 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:33 | itistoday | rhickey: k, thanks |
| 17:33 | rhickey | Chouser: while a direct attempt at cinc is possible, I have a large list of things I want to do differently |
| 17:33 | Lau_of_DK | I know the feeling, we just climbed that hill with ClojureQL :) |
| 17:34 | rhickey | e.g. not use reflection and concrete class instances during compilation, requires abstracting out type info provision |
| 17:34 | rhickey | but maybe there's a layered approach, I'll try to knock some of my notes into the wiki |
| 17:36 | itistoday | as 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:37 | itistoday | or is at as simple as simply treating it as you would with java? |
| 17:38 | Lau_of_DK | rhickey: tried emacs' assembla-wiki-mode ? |
| 17:39 | rhickey | itistoday: coarsely, use Clojure data structures and facilities for your models, use java for I/O |
| 17:40 | itistoday | rhickey: 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:42 | Chousuke | can't do IO in transactions |
| 17:42 | Chousuke | you could use agents |
| 17:42 | itistoday | Chousuke: ah, so have an agent that's responsible for the IO? |
| 17:42 | Chousuke | something like that. |
| 17:42 | rhickey | itistoday: 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:43 | itistoday | thanks, i'll stop bugging you guys with questions now and do some more reading :-) |
| 19:08 | JAS415 | does the -> operator only work for functions that are associated with a name? |
| 19:09 | hiredman | nope |
| 19:09 | hiredman | but it isn't as pretty |
| 19:09 | hiredman | ,(-> "foo" (#(.toUpperCase %))) |
| 19:09 | clojurebot | "FOO" |
| 19:09 | hiredman | you just double up on the parens |
| 19:09 | clojurebot | ΜΟΛΩΝ ΛΑΒΕ |
| 19:10 | hiredman | clojurebot: what? |
| 19:10 | clojurebot | what is java |
| 19:10 | JAS415 | oh you have to do an extra set of parens |
| 19:46 | ozzilee | Compojure seems to include the path my application is deployed at when matching routes. Does anyone know if that's intentional? |
| 19:47 | ozzilee | i.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:47 | grrrt | "myapp" is your servlet's context path I assume |
| 19:48 | grrrt | if 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:50 | ozzilee | grrrt: I can do that in tomcat, but I'd only be able to have one app per domain in the root context, correct? |
| 19:51 | grrrt | that sounds plausible yes |
| 19:52 | ctdean | Do you mean when using defserver? I'm not following. |
| 19:53 | ozzilee | ctdean: Using defroutes. (defroutes app (GET "*" (str (params :*)))). |
| 19:53 | ozzilee | (defservice app) |
| 19:54 | ozzilee | Compile 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:55 | ctdean | I see. I've never put my stuff in a .war, so I have no idea. |
| 19:56 | ctdean | The plain vanilla (e.g. from a repl) doesn't prepend a path |
| 19:58 | ozzilee | ctdean: Yeah, it's only an issue when deploying in a servlet container. |
| 19:59 | ctdean | Try the compojure mailing list, they're responsive |
| 20:02 | ozzilee | ctdean: I will eventually. |
| 20:09 | Drakeson | is it possible to insert break-points in function definitions in slime? |
| 20:09 | Drakeson | (e.g. the way you can C-u M-C-x a defun in elisp) |
| 20:10 | grrrt | Drakeson: I just tried that with cljdb - http://georgejahad.com/clojure/cljdb.html |
| 20:10 | grrrt | it did work |
| 20:10 | Drakeson | thanks |
| 20:10 | grrrt | no worries |
| 20:17 | JAS415 | is it a common problem for clojure-dev to crash if repl output is too large? |
| 20:17 | JAS415 | i keep having to force-quit eclipse it seems |
| 20:38 | Drakeson | Do you happen to know of a way to control firefox through java (and ultimately through a clojure repl)? |
| 20:40 | hiredman | Drakeson: are you just looking to webbrowser programaticly? |
| 20:40 | hiredman | htmlunit works pretty well |
| 20:40 | Drakeson | hiredman: not just that. |
| 20:41 | Drakeson | there 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:53 | durka42 | there is mozrepl but i think that's javascript |
| 20:54 | durka42 | but you don't use clojure to script pages (unless you're using clojurescript), so how would it be as useful as firebug? |
| 20:55 | Drakeson | durka42: 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:00 | rhickey | ,(partition 3 1 nil (range 10)) |
| 21:00 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$partition |
| 21:00 | rhickey | hrm, new partition does: |
| 21:00 | rhickey | user=> (partition 3 1 nil (range 10)) |
| 21:00 | rhickey | ((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:03 | rhickey | seems to me partition with step 1 should never use the pad |
| 21:03 | rhickey | user=> (partition 3 1 [42] (range 10)) |
| 21:03 | rhickey | ((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:09 | Chouser | it should include (9 42 42) as well? |
| 21:10 | Chouser | shouldn't |
| 21:10 | rhickey | no, once it has produced a partition containing the last element of the coll it should be done |
| 21:11 | Chouser | hm... yes |
| 21:11 | Chouser | (partition 3 2 nil (range 5)) should end with (2 3 4) |
| 21:12 | rhickey | I've kicked https://www.assembla.com/spaces/clojure/tickets/120 back to Dimitry |
| 21:22 | Drakeson | ~ |
| 21:22 | clojurebot | what is java |
| 21:22 | Drakeson | ~paste |
| 21:22 | clojurebot | lisppaste8, url |
| 21:22 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 21:22 | lisppaste8 | Drakeson pasted "original partition" at http://paste.lisp.org/display/82474 |
| 21:23 | lisppaste8 | Drakeson annotated #82474 "modified" at http://paste.lisp.org/display/82474#1 |
| 21:26 | lisppaste8 | Drakeson annotated #82474 "better" at http://paste.lisp.org/display/82474#2 |
| 21:28 | Chouser | if you use 'seq' as the opposite of 'empty?', then you can use if-let instead of repeating the drop expr |
| 21:29 | Drakeson | sorry, I didn't get it |
| 21:30 | Drakeson | which drop expression is repeated? |
| 21:30 | Chouser | (if-let [cont (seq (drop n s))] (cons p (partition n step pad cont)) (list (take n (concat p pad))))) |
| 21:31 | Chouser | oh |
| 21:31 | Chouser | nm. |
| 21:31 | Chouser | :-) ignore me. |
| 21:31 | Drakeson | :p |
| 21:32 | seths | I wish the api, special_forms, and kin pages on clojure.org were wiki pages |
| 21:33 | Drakeson | kin pages? |
| 21:33 | seths | it's frustrating when things like nthrest are mentioned in multiple places but don't exist |
| 21:33 | Drakeson | how is the web site managed? is it under git, by any chance? |
| 21:34 | Chouser | it's a wikispaces site |
| 21:35 | seths | must be private, wikispaces.com says this: Your search - Clojure - did not match any documents. |
| 21:37 | Chouser | seths: you're welcome to write up a list of errors and post it to the google group. |
| 21:37 | seths | good point |
| 21:37 | Chouser | it would be great if it were in git |
| 21:38 | moc` | 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:41 | Chouser | moc`: by quoting the list '(+ -) you're preventing the evaluation of each of those symbols |
| 21:42 | Chouser | you wanted a list of 2 functions, but instead you have a list of 2 symbols. |
| 21:42 | Chouser | if you use [+ -] instead, each of those symbols will be evaluated, and you'll have a vector of functions. |
| 21:42 | moc` | Chouser: OK, I get it. |
| 21:43 | Chouser | ,('+ 1 2) |
| 21:43 | clojurebot | 2 |
| 21:43 | moc` | Chouser: Thanks. It was doing my head in. |
| 21:43 | Chouser | you're welcome. It's why we're here. :-) |
| 21:47 | seths | ok, Rich renamed nthrest to nthnext on Feb 17th 2009 |
| 21:48 | seths | commit b8e333fb3437dca760f16136ed074a4dd463fe35 |
| 21:48 | dreish | Extra 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:48 | dreish | (That should have been to moc`) |
| 21:49 | dreish | But it doesn't throw an exception if the first arg isn't a map. It just returns the not-found value (or nil). |
| 22:17 | Chouser | anyone here used enlive on xml docs? |
| 23:01 | JAS415 | gotta say |
| 23:01 | JAS415 | i love memoization as a primitive |
| 23:04 | Chouser | anyone used enlive at all? |
| 23:04 | grrrt | yes I have |
| 23:04 | grrrt | just for tagsoup though |
| 23:04 | Chouser | well, that may still help me. |
| 23:04 | grrrt | I love the idea of enlive |
| 23:05 | Chouser | I just need a working example -- input html and 'select' call |
| 23:05 | Chouser | for 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:05 | clojurebot | for is not used enough |
| 23:05 | Chouser | I've got my xml parsed into a format I think enlive wants. |
| 23:06 | Chouser | but (enlive/select xml [:description]) returns an empty seq |
| 23:06 | grrrt | I'll rummage through my clojure snippets for a bit, I must have something there |
| 23:06 | Chouser | in fact, anything I put in place of [:description] returns an empty list. |
| 23:07 | Chouser | eh, I but that means xml is in the wrong format. |
| 23:07 | Chouser | bet |
| 23:08 | grrrt | what format is it? |
| 23:08 | grrrt | I could just load a plain text file as a resource: (html-resource "templates/my-template.html") |
| 23:09 | Chouser | yeah, but I'm trying to avoid needing tagsoup, since I just need xml. |
| 23:09 | Chouser | if I were less stubborn this wouldn't be a problem |
| 23:09 | grrrt | ah sure, I see |
| 23:09 | Chouser | xml is fron (xml/parse foo) |
| 23:09 | grrrt | hm I think I have only ever used enlive's deftemplate macro |
| 23:10 | Chouser | (enlive/select (xml/parse input-stream) [:description]) |
| 23:12 | Chouser | woo! got it |
| 23:13 | Chouser | (enlive/select [(xml/parse input-stream)] [:description]) |
| 23:13 | grrrt | ah |
| 23:28 | holmak | Has anyone done much work with using Swing or another Java UI toolkit from Clojure? |
| 23:28 | holmak | More importantly, has anyone found a way to make it a tolerable experience? |
| 23:28 | grrrt | I'm working on something that makes using SWT easier |
| 23:28 | holmak | May I ask what approach you are taking? |
| 23:29 | grrrt | well (it's a work in progress still) |
| 23:29 | grrrt | I have created an easy way to specify SWT widgets in a tree |
| 23:29 | holmak | aha |
| 23:30 | holmak | (I had given some thought to this problem as well.) |
| 23:30 | grrrt | you can basically say things like (shell {:outlet :my-shell} (menu-bar (menu "File" (menu-item "New" {:shortcut \N})))) etc |
| 23:30 | holmak | I never realized how incredibly procedural Swing is until I used it from Clojure |
| 23:30 | grrrt | I know - I'm fighting SWT because everything has to happen in the UI thread |
| 23:31 | holmak | Well, I think that problem is tolerable if you just make a queue that you deposit UI calls into |
| 23:31 | grrrt | I have a separate namespace with functions that actually create the widgets |
| 23:31 | holmak | in Swing, there's SwingUtilities/invokeLater, of course |
| 23:31 | grrrt | they do (in-ui (Shell. (display))) |
| 23:31 | holmak | handy |
| 23:32 | holmak | So, here is the tricky problem I have -- how do you handle events, and how do you handle changing state of widgets? |
| 23:32 | grrrt | SWT uses events like selection, keydown etc |
| 23:32 | holmak | I'm not familiar with SWT |
| 23:33 | hiredman | http://gist.github.com/107140 <-- EDT macro is very useful |
| 23:33 | grrrt | I can respond to a menu selection by doing (menu "New" {:on-Selection (fn [evt] (println "Menu selected!"))}) |
| 23:33 | holmak | Seems solid -- so how would you mutate widgets, like, to append to a text field? |
| 23:33 | hiredman | generally I have (future do stuff) in an event listener |
| 23:33 | hiredman | (to push stuff of EDT) |
| 23:33 | hiredman | off |
| 23:34 | grrrt | well, the structure of widgets I mentioned earlier |
| 23:34 | grrrt | all widgets support an :outlet option, such as {:outlet :my-label} for some text label |
| 23:35 | grrrt | the whole widget structure returns a map with all widgets that have an outlet defined |
| 23:35 | grrrt | if a button-push calls the "change-text" function, I can just do (.setText (:my-label *outlets*) "New Text") |
| 23:36 | holmak | nice |
| 23:36 | grrrt | because 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:36 | grrrt | When it's slightly more polished I'm planning to put my efforts online somewhere |
| 23:37 | grrrt | (I stole the term outlets from Mac OS X Cocoa) |
| 23:37 | holmak | It certainly seems like the Clojure community would benefit from a nice declarative GUI library/wrapper |
| 23:37 | grrrt | yes, it's tricky to combine functional programming with a gui |
| 23:37 | holmak | Your approach is similar to the thoughts I had |
| 23:37 | holmak | I started out thinking about Django templates |
| 23:37 | holmak | or really, and web framework template, take your pick |
| 23:38 | holmak | where you have little slots that you can plug your content in |
| 23:38 | grrrt | yes indeed |
| 23:38 | holmak | Because 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:38 | holmak | Sorry, that was a bit of a run-on |
| 23:38 | grrrt | :) no worries |
| 23:39 | holmak | The trick is that you don't want to recreate the GUI every update |
| 23:39 | holmak | unlike on teh web |
| 23:39 | grrrt | yeah, you need some kind of context to store your UI objects in |
| 23:39 | holmak | Right now I am doing horrific things with Swing in the name of getting another project done |
| 23:40 | grrrt | heh. I started out wanting to get a window going to do some graphics, then the "design the perfect world" syndrome kicked in |
| 23:40 | holmak | Ideally, you would have a pure Clojure data structure, like a map, that you could throw at your GUI "handle", and say, "update, GUI!" |
| 23:40 | holmak | and everything would drop into its slot |
| 23:41 | grrrt | hm, that sounds interesting |
| 23:41 | grrrt | I don't see why you couldn't do that |
| 23:41 | holmak | Eh, there has to be some kind of compromise between performance and declarativeness |
| 23:41 | hiredman | oh god |
| 23:41 | hiredman | foreclojure |
| 23:41 | hiredman | :| |
| 23:41 | holmak | It's definitely an interesting problem |
| 23:42 | holmak | hiredman: where? |
| 23:42 | hiredman | the google group |
| 23:42 | grrrt | wow. just read the latest msg |
| 23:43 | holmak | hahaha |
| 23:43 | holmak | That's both witty and terrible |
| 23:43 | holmak | It's much harder to come up with good Clojure project names than, say, Python project names |
| 23:43 | grrrt | holmak: are you considering a situation where the UI is mostly updated in response to user actions? |
| 23:44 | hiredman | ~Xiphojura |
| 23:44 | clojurebot | 2009:Jan:29:16:03:17 <hiredman> I call Xiphojura |
| 23:44 | grrrt | or from a background process |
| 23:44 | holmak | "I'm making a spreadsheet, I'll call it, uhh, pySpreadsheet!" |
| 23:45 | holmak | grrrt: I don't really know where I was going with that thought. I didn't have a chance to think about it much. |
| 23:46 | holmak | But this entire thought process was triggered by trying to work with the Swing Tree widget. |
| 23:46 | holmak | Which is, in fact, a suite of about a dozen classes and a real nightmare. |
| 23:46 | hiredman | you could have an agent with a watcher |
| 23:47 | grrrt | hiredman: how does that work? |
| 23:47 | holmak | Oh, very interesting -- use the watcher to trigger changes, instead of validating changes? |
| 23:47 | hiredman | you alter the map in the agent, and the watcher updates the gui state based on the new values in the map |
| 23:49 | hiredman | would make for an interesting toolkit design |
| 23:49 | grrrt | hm. that sounds good |
| 23:49 | holmak | I should write these things down. |
| 23:50 | grrrt | neh just implement it |
| 23:50 | holmak | About the watchers, though: asynchronous madness! |
| 23:50 | holmak | If only we had a language well suited to dealing with massive concurrency... |
| 23:51 | hiredman | well, updates will be serialized anyway |
| 23:52 | hiredman | because the watcher will dump them on the edt |
| 23:52 | holmak | Oh I know. It's just that I would never devise a system using three parallel threads of execution in any other language. |
| 23:52 | holmak | But here, it practically makes sense! |
| 23:53 | hiredman | well, having gui stuff going on in multiple threads is a "dead dream" so you would need at least two threads anyway |
| 23:53 | grrrt | hiredman: does Swing's invokeLater work with "nested" calls? |
| 23:54 | grrrt | i.e. could you do (EDT (EDT (....)) ? |
| 23:54 | holmak | I feel like that would just invokeLater some invokeLaters |
| 23:55 | grrrt | my SWT equivalent would block if I tried that. |
| 23:55 | hiredman | grrrt: invokelater just ques up Runnables on swing's Executor |
| 23:55 | grrrt | ah right |
| 23:55 | holmak | hooray queues |
| 23:55 | hiredman | if EDT used invokeandwait or whatever it's called, then you would have a problem |
| 23:55 | grrrt | yeah |
| 23:56 | holmak | So, how do you feel about SWT? Either of you? I'm using Swing because it was closer, but I'm open to conversion. |
| 23:56 | grrrt | I don't know much about swing, can't really compare |
| 23:57 | grrrt | SWT seems reasonably straightforward, but I'd hate to do it in java |
| 23:57 | grrrt | 5 lines of code for a simple menu item... |
| 23:57 | hiredman | swt is full of native code :( |
| 23:57 | grrrt | true |
| 23:59 | grrrt | but you can download or build it for many platforms |
| 23:59 | hiredman | would rather just depend on the jre |