#clojure log - Dec 07 2008

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:03 Chouser: clojurebot: tar pit is http://web.mac.com/ben_moseley/frp/paper-v1_01.pdf

0:03 clojurebot: In Ordnung

0:04 Chouser: arohner ^^^

0:05 arohner: thanks

0:12 lisppaste8: scgilardi pasted "map -> retaining head" at http://paste.lisp.org/display/71730

0:13 scgilardi: the paste is a simple example of the heap exhaustion problem we've been kicking around in the google group

0:14 arohner: scgilardi: wow, nice demonstration

0:15 scgilardi: thanks! I had some misadventures analyzing the implementations involved, but it's good to have a simple example.

0:16 Chouser: yeah, that's impressive. I poked at the question a little but got nowhere.

0:16 so have you figured out why?

0:17 scgilardi: I haven't. puzzler figured out that map was key. I spent time analyzing filter, but it wasn't productive. I don't see what the problem with map is (and I'm not even sure it is a problem with map, just that it's involved)

0:21 Chouser: It's not exhausing the heap for me.

0:22 I added an extra 0 and it's still running, but the memory graph is jagged, up and down.

0:22 oh, there it went

0:22 java.lang.OutOfMemoryError: GC overhead limit exceeded (NO_SOURCE_FILE:0)

0:23 scgilardi: It's probably any "realized" chain of lazy-cons's. I see now that Range implements first and rest without allocating. (map identity (range...)) will allocate a LazyCons object for each item as long as some code retains the head. It looks to me like it's a temporary on the stack that's retaining the head.

0:24 Chouser, are you using YourKit?

0:24 Chouser: not just now, no.

0:24 scgilardi: wondering where the graph was

0:24 Chouser: I was looking at my whole system memory graph

0:24 scgilardi: oh ok

0:24 Chouser: not definitive, I know. :-)

0:25 scgilardi: I can't tell if you've already been plagued with reports... so just in case... your'e aware the irc log has stopped providing logs?

0:27 Chouser: oh! no, nobody's mentioned.

0:31 scgilardi: fixed, thanks.

0:31 scgilardi: cool, thanks

0:38 rzezeski: scgilardi, I get an OutOfMemoryError when running (count (line-seq (reader "/path/to/csv/with/million/plus/lines"))) Is this also related to the same problem you are discussing, or am I doing something wrong there?

0:39 timjr: How do you guys lay out (cond ...)?

0:40 If the tests and the exprs are short, it's easy, one line per pair... but if you have some long ones, it gets messy

0:40 Chouser: any way that keeps the tests and results from starting in the same column

0:41 timjr: hm, that sounds reasonable, though I guess I'll have to teach emacs about it

0:42 I miss the extra parens :)

0:42 Chouser: hm, looks like clojure/core.clj has three examples of conds with multi-line results

0:42 two of which violate my rule. :-)

0:43 timjr: the one in the doc macro looks good anyway because of the backquotes

0:44 Chouser: timjr: yes, please teach emacs to do something more sensible, and then tell rhickey to use it so load-lib is less confusing.

0:44 timjr: someplace I saw somebody leaving a big blank line between each pair... that's too much space for me though

0:44 holmak: I often put comments in between

0:44 hiredman: I indent the result of a condition one level more then the condition

0:44 scgilardi: rzezeski: if you're holding on to the head of the line-seq outside that loop, then count will cause it to become fully realized in memory... one LazyCons object per line. That would use a lot of memory. If you're not, then count shouldn't and it should be O(1) for memory.

0:44 Chouser: I try hard to fit each on a line (write new functions or whatever)

0:44 holmak: Since a branch like that usually merits commenting anyway.

0:45 Chouser: otherwise like hiredman said.

0:45 hiredman: comas can be used for all kinds of grouping

0:45 cause they are whitespace

0:45 Chouser: good point! (cond t1 ,,r2 t3 ,,r3)

0:46 timjr: yeah, that's an interesting idea

0:46 Chouser: heh

0:46 I should just sprinkle prefix commas around to panic CL programmers.

0:46 hiredman: I kind of embarrased to say that, even will all the technical cool stuff in clojure, comas as whitespace is one of my favorite features

0:46 I am

0:46 Chouser: (+ 1 ,2 3)

0:47 hiredman: I am

0:47 ugh

0:47 typing is not working for me right now, so maybe irc is not the best choice

0:48 rzezeski: scgilardi, that is all the code minus the namepsace/imports. I tried that weeks ago and was confused as to why it was running out of memory, but just gave up and forgot about the problem until now when I just read that thread in the google group and your example. It seems like this is a related problem?

0:50 replaca: for conds, I've been going with the blank lines between pairs. Works for me.

0:50 scgilardi: rzezeski: it could be related. if the expression you posted is the entire thing you're running then it looks to me like it is the same issue.

0:51 rzezeski: scgilardi, do you think it would benefit the thread at all if I posted my example? Or is everything pretty well covered?

0:52 scgilardi: I think it would be useful. Until we have a real diagnosis, reproducible cases can't hurt.

0:52 worst case, we'll both learn something.

0:52 rzezeski: OK, I'll add a comment then

0:53 scgilardi: cool, thanks

0:53 rzezeski: Yea see I figured it was a problem, but since I'm so new to Lisp/Clojure I guess I felt a little nervous to start claiming things are borken

0:54 broken*

0:56 Chouser: rzezeski: that's a healthy attitude. Similar self-doubt has saved me from many embarrassing posts.

0:56 scgilardi: I think a question like: "/good description of a situation/ surprised me, I expected x and got y" is a good way to approach that kind of thing. And it's even likely that you're not the only one who would be surprised. All the likely replies to such a question will be helpful ones.

1:00 rzezeski: When I first came across the problem I did get out JSwat (which didn't help me much because I've never used it before) and looked at some of the related clojure source, but it was a lot to take in and I couldn't see anything obviously wrong (nor did I expect to, given the smart minds working on this stuff). Anyways, I gave up after a couple of hours and figured either I'd figure it out later down the road or someone else would hit t

1:08 Hopefully I can upload a 8.9M zip to the clojure group, heh

1:08 scgilardi: I wasn't recommending that.

1:08 People can come up with their own big files. :)

1:08 rzezeski: too late, it's already there :)

1:10 scgilardi: In fact, a million linefeeds would behave the same way and I bet that compresses down to under 1K.

1:11 rzezeski: yea, that probably would have been a better solution...but at least disk space is cheap, and I imagine it can be deleted if need be

1:20 alright I added a comment to the thread, I also forgot to mention that if I replace count with dorun the expression returns just fine

1:34 Chouser: rzezeski: I think I see what's causing the issue you found.

1:35 rzezeski: ok, same problem as scgilardi or something different?

1:37 Chouser: I think your's is directly related to the implementation of count

1:38 rzezeski: oh i see

1:38 well I also have the problem when I call map on the sequence

1:38 scgilardi: count -> size -> count -> for loop. is the for loop wrong?

1:39 Chouser: RT.count -> ASeq.count -> for loop

1:40 but the for loop is run in an instance method of the head of the seq.

1:40 so 'this' retains the head

1:40 scgilardi: I saw it as ASeq implmentation of Collection. Maybe there was a special case before. Wow, cool find.

1:40 rzezeski: in fact, I should state that I initially ran into the problem while trying to map each line of the file to a map (ie dictionary), when that failed I thought, well lets see if I can even count the lines in the file

1:41 scgilardi: lazy is hard

1:41 Chouser: are all lazy sequences instances of LazyCons?

1:42 scgilardi: no, for example ranges are not

1:43 rzezeski: so I had a method "line-to-map" that took a line a returned a map and then I evaluated "(map line-to-map (line-seq (reader "big.csv")))" which also failed. But I wonder if that's failing because I'm making 1M+ map instances?

1:44 scgilardi: clojurebot: lazy is hard

1:44 clojurebot: Ok.

1:45 rzezeski: lazy is hard, let's go shopping

1:57 Chouser: rzezeski: you're building clojure from svn?

1:57 rzezeski: yep

1:57 r1145

2:00 Chouser: you might try this patch and see if it fixes your 'count' problem: http://paste.lisp.org/display/71735

2:01 bleh.

2:02 rzezeski: I was actually trying something similar to what you just posted

2:02 hold on, I'll try your fix now

2:02 yep, all good

2:02 user=> (load-file "out-of-mem.clj")

2:02 1206342

2:03 Chouser: ok. I don't think that patch is actually acceptible, but I don't see how to solve it "right"

2:03 rzezeski: yea, I think it proves your theory that it's because the method call is in the instance of the head

2:03 Chouser: both RT.count's local o and ASeq.count's this point to the head of the list.

2:04 RT.count can't pass o to anthing else without retaining the head, as far as I can figure, so the counting has to be done right there, which is ... ugly.

2:08 rzezeski: yea that was the obvious initial answer to me, but I don't know the Clojure source at all, I would imagine there is a "cleaner" solution out there

2:12 Chouser: Unless there's some way to tell Java to pass value to a function while "forgetting" it itself, I don't see how else it can be solved.

2:12 rzezeski: it also looks like this could possibly affect methods like toArray as well?

2:13 Chouser: I can't do o=null before calling ASeq.count, and doing it after is too late.

2:15 well, toArray's going to have to hold the whole thing in memory anyway.

2:15 rzezeski: so do you still think this problem is separate from what scgilardi et all are describing, or could these situations somehow be related?

2:15 Chouser: I guess as it is it may hold two copies when it could possibly get away with holding one.

2:17 rzezeski: it seems likely it's a similar type of problem, but that's not a very strong statement since both are memory overflows when dealing with large lazy seqs.

2:17 rzezeski: Right, but lets say I could fit that million plus array in memory, I would never be able to do he conversion because 1) it calls count, and 2) It's doing the same iteration thru the sequence as count is

2:17 Yea I guess we will see with time

2:19 scgilardi: 'nite gents

2:38 rzezeski: Chouser, I think it's more than just the fact that the implicit "this" is the head, but also the fact the the local variable "o" in RT.count is also a reference to the head...correct? I tried making the count in ASeq static, and making sure it didn't hold the head, but that still didn't work

2:41 Chouser: rzezeski: yes

2:42 rzezeski: Is that what you were saying when you said "I can't do o=null before calling ASeq.count, and ..."

2:43 Chouser: yeah, I don't know of any way to delegate that work without retaining the head of the seq in o in the meantime.

2:43 rzezeski: If so It looks like I'm 25 minutes behind you :)

2:43 Chouser: sorry i didn't explain myself better.

2:43 rzezeski: nah it's ok

2:43 it makes perfect sense now that I have seen it myself

2:45 well, I think one way to do it (not saying it is good) might be to spawn a new thread to do the count and then immediately after set o to null?

2:46 Chouser: yikes.

2:46 ooh!

2:46 that was the push I needed.

2:46 rzezeski: haha, ok, glad I could get you going

2:46 Chouser: why not put o in a little object, say an array of length 1

2:46 pass *that* into a static ASeq.count

2:47 ...which could take the head of the seq, null out the array, and proceed to walk the seq

2:47 rzezeski: ohhh and set the arr[0] to null

2:47 Chouser: yes

2:47 rzezeski: yea

2:47 that could work

2:48 Chouser: well, I'll leave that to you. I should have been in bed hours ago.

2:48 rzezeski: Ok, yea it's 2:45 AM here, I'll give it a quick go before I go to bed

2:49 Are you going to stay logged in or is there an email addy I can send to let you know the results?

2:49 Chouser: my irc client will be here, or you can post to the group.

2:50 good luck!

2:50 rzezeski: ok

2:50 thx for all your help

2:53 Chouser: I think clojure.lang.Box may be for just such purposes.

2:55 or maybe not. anyway, bed, for real.

3:28 rzezeski: Chouser, the solution did work, I'm just not sure if my patch is very good. Plus there may be better solutions. I guess I'll just post your solution on the google group for now and see what others say

8:20 mibu: I have a few questions about hierarchies (derive, isa?, etc). can anyone help?

8:24 rhickey: mibu: sure

8:25 mibu: rhickey: I kinda understood the hierarchy mechanism in clojure was meant for multimethods, but because it's abstract, it can also be used for other stuff using :keywords, is that right or did I get this wrong?

8:26 rhickey: mibu: you can call any of the hierarchy fns for any purpose you like

8:27 mibu: rhickey: so how one uses keywords in derive? the second assert in the code prevents that or I'm doing something wrong...

8:27 rhickey: but isa? is only used by multimethods, doesn't replace keyword equality

8:27 hierarchy names must be ns-qualified

8:28 :my-ns/a-key

8:28 or ::a-key

8:28 ditto for symbols used hierarchically

8:28 mibu: rhickey: oh. why is that?

8:28 rhickey: to prevent clashes, as both you and I independently decide how :this and :that are related

8:29 It's a global hierarchy space

8:29 mibu: rhickey: but if I use my own hierarchy, how could :this and :that interfere with your hierarchy? (not in global-hierarchy)

8:30 rhickey: just checking - in that case the check is too strict

8:31 mibu: rhickey: wouldn't it be more useful to remove that assert on the [h tag parent] case and just leave it on in [tag parent] case?

8:31 rhickey: yes

8:32 mibu: rhickey: you're going to change it then?

8:32 rhickey: not right this second - why not post a message on the group asking for it?

8:34 mibu: rhickey: ok, I will. you mentioned isa? is only used in multimethods. why not use it for any kind of hierarchies?

8:34 kib2: rhickey: Hi. I'm using clojure.contrib.duck-streams, but I don't find a way to save a file to utf8. Did I miss something ?

8:35 rhickey: mibu: I was saying it is only used by multimethods by Clojure, you can use it for whatever you want.

8:35 mibu: rhickey: ah. got it. thanks for your help.

8:36 rhickey: kib2: don't know, maybe a contrib user/author can chime in

8:36 kib2: rhickey: ok, thanks

8:51 mibu: rhickey: is there a way to generate warnings instead of assert throws?

8:55 AWizzArd: mibu: yes, simply try/catch the error

8:55 when you have (def x 4) then you can say: (try (assert (= x 4)) (catch java.lang.Exception e (println "Hello")))

8:56 (or simply Exception instead of java.lang.Exception)

8:58 mibu: AWizzArd: I mean in a more idiomatic way, such as (warn (= x 4)), so if you use my code and want to turn off warnings, you could simply do that.

9:18 clojurebot: svn rev 1146; added doc string for *agent*

9:26 emacsen: Morning all

9:26 DC folks: Quick reminder, clojure study group today

9:27 :)

9:35 RSchulz: emacsen: Can you clarify? By DC do you mean Washington DC? And the study gruop is people meeting in person?

9:35 Or is an on-line thing?

9:35 emacsen: RSchulz, by DC I mean the DC area, yeah

9:35 and by study group, I mean we're meeting at some place called Chief Ike's

9:35 at 1

9:36 (until we find a better place, I think)

9:37 RSchulz: OK. Well, 3,000+ miles is a bit much for me to travel for that...

9:37 emacsen: clearly Clojure doesn't mean enough to you :)

9:37 RSchulz: Everything has its limits...

9:37 emacsen: :)

9:38 RSchulz: The last I checked that map of Clojure users, I noticed a distinct east-of-the Mississippi skew.

9:38 I also thought I saw the outlines of The Sprawl there!

9:38 emacsen: why do you think that is?

9:39 RSchulz: I don't know, really. Do you have any ideas?

9:40 emacsen: Lisp, I think generally has an East Coast bias

9:40 well actually

9:40 RSchulz: Yeah, I was going to suggest that. But McCarthy himself is here at Stanford!

9:40 emacsen: #1 is Rich has been to more East Coast events

9:40 #2 Lisp is more East Coast

9:40 RSchulz: Yeah. I hope I can get him to visit the SVJUG when he's out here for Java One next year. Those events are too expensive for me.

9:41 emacsen: #3 I think there's more of an academic interest vs pragmatic interest right now

9:41 RSchulz: Possible on #3. I'm kind of academically inclined myself.

9:42 That's not really a bad thing. Language design is not as easy as many people seem to think. We don't need more Groovy's...

9:43 emacsen: The one thing I kinda would like to see soon from Clojure is a cohesive style guide

9:43 convention can take you a long way

9:43 RSchulz: I'm comfortable with creating my own style. Besides, it seems there's less disagreement about style among Lispers than, say, Java programmers.

9:44 It must be a blub thing.

9:46 emacsen: eh...

9:46 like, simple one but there's no p or ? in Clojure

9:47 RSchulz: You mean as a naming convention? It seems mostly to be '?'.

9:47 Chousuke: clojure core uses ?

9:47 emacsen: does it? Okay I'm lame I've not seen it yet

9:47 stuarthalloway, lucky you, the study group is focusing on your book

9:48 so like 10 people bought it just for this

9:48 RSchulz: Yeah, and we're getting impatient for the next beta!

9:48 No pressure, though.

9:48 Chousuke: I prefer ? over p myself.

9:49 RSchulz: Chousuke: I agree.

9:49 emacsen: yeah no one likes p

9:49 except spoken

9:49 RSchulz: You can just use a rising inflection...

9:49 emacsen: p is funnier

9:49 RSchulz: Then instead of saying "huh?" you can say "p?"

9:50 emacsen: no

9:50 you'd use it like "lunch-p ?"

9:50 RSchulz: Yeah. I've been around lisp programmers...

9:50 emacsen: stuarthalloway, where are you geographically?

9:52 RSchulz: He's in a dungeon working on a book.

9:53 duck1123_: splitp soup?

10:07 stuarthalloway: http://local.google.com/maps?f=q&hl=en&geocode=&q=100+Europa+Dr,+Chapel+Hill,+NC+27517&sll=37.0625,-95.677068&sspn=49.176833,114.257812&ie=UTF8&z=16&g=100+Europa+Dr,+Chapel+Hill,+NC+27517&iwloc=addr

10:08 although I do move around a bit

10:17 emacsen: NC eh? Well if you're in DC, give us a ping

10:25 AWizzArd: Hmm, I have a little Clojure function that is easily outperformed by Java, by a factor of about 50-100! Help!

10:26 http://paste.lisp.org/display/71753

10:26 Any ideas if type hints could help here?

10:27 emacsen: generally the answer to "will type hints help" is yes

10:36 RSchulz: But is it not the case that if you just toss them in, you'll end up with code with limited numeric range?

10:37 Stuarts's recent podcast interview mentions the ability to dynamically shift from int to long to BigInteger.

10:37 But of course, that makes the code not quite so elegant, so you have to decide whether the performance you get justifies the more complex coding.

10:45 stuarthalloway: RSchulz: the cool thing is that Clojure has a middle ground, where overflows are exceptional

10:46 RSchulz: Right. That's the way you can get dynamic range adjustment, right?

10:46 That's how I understood your remarks in that interview.

10:46 stuarthalloway: no, that's the slow way

10:47 RSchulz: Do you have a blog on this tactic somewhere? If not, you should write one. What you said was tantalizing, but I don't think I really understood it properly.

10:47 (Even thought I went back and listened a second time...)

10:47 gnuvince_: Good morning all

10:48 RSchulz: Mornin' gnuvince_

10:48 Is it pure coincidence that there are two virtually identical nicks here, gnuvince and gnuvince_ ?

10:49 gnuvince_: RSchulz: gnuvince_ is me at home and gnuvince is me at work

10:49 RSchulz: Ah. Your dual nature.

10:49 gnuvince_: And basically, I just leave work in a hurry without ever bothering to close down irssi there

10:49 RSchulz: Shame on you.

10:49 Hurrying will just bring you to the end of your life that much more quickly.

10:50 gnuvince_: Hurrying out of work, though?

10:50 RSchulz: Well, that's a grey area.

10:50 stuarthalloway: RSchulz: http://paste.lisp.org/display/71754

10:51 RSchulz: I love the "ask and you shall receive" mentality!

10:51 stuarthalloway: that's from the book, and hopefully consistent with what I said in the podcast :-)

10:51 RSchulz: So isn't there a fourth way, where you use the exceptions to shift from native to BigInteger?

10:51 Is it in beta3?

10:51 stuarthalloway: no, and yes

10:52 it is in section 3.2

10:52 RSchulz: Oh, yeah, I recognize it now that I think of it. I guess I went pretty quickly over that part. Numbers don't do much for me...

10:53 stuarthalloway: until people post with subject lines like "Elegant but very slow" on the mailing list...

10:53 RSchulz: So why isn't there the fourth way? It seems plausible. Is there something I'm not seeing?

10:53 Well, it's email. People often overstate their case. And, of course, there's just the fact that a lot of people still need to learn a lot about Clojure. I certainly do.

10:54 stuarthalloway: seems plausible to me too, but the interplay between the logic that seems plausible and VM optimizations may be subtle

10:54 RSchulz: Subtle's good.

10:55 stuarthalloway: sometimes. I meant more along the lines of "the fourth way can be implemented, but it defeats some optimizations and doesn't buy you much"

10:56 RSchulz: I see. Perhaps there are cases where either: a) You can tell in advance what the ultimate range required will be on an call-by-call basis

10:56 Or b) You can run the algorithm in native mode until it gets an overflow exception and then start over with BigInteger.

10:57 With (b) you don't have exception handling integrated in the inner loops of the code, but you lose the ability to shift the calculation in-place, necessitating the starting over.

10:58 I'm just throwing this out. I'm not sure it makes much sense, at least often.

10:59 stuarthalloway: it all sounds reasonable

11:00 even simple enough that either (a) or (b) might be done as a JIT optimization for any JVM language

11:01 RSchulz: Well, those JIT folks have done some pretty impressive things in the past ten years.

12:17 Chouser: AWizzArd: As I understand it, 'range' produces boxed numbers, so even if you add type hints you'll still be unboxing for every iteration.

12:17 oh, that's only in regards to find-factors, I guess.

12:19 AWizzArd: find-factors2 should benefit a lot from type hints.

14:04 Lau_of_DK: Good evening gents

14:07 danlarkin: afternoon

14:10 Lau_of_DK: Chouser: Im _really_ impressed by your solution to Euler83, its beautiful

14:11 AWizzArd: apropos Euler.. does anyone have an idea how to speed up Clojure by a factor of 100? http://paste.lisp.org/display/71753

14:12 Chouser: Lau_of_DK: why thank you. For me, that required lots of work. :-)

14:15 AWizzArd: http://paste.lisp.org/display/71753#1

14:16 Lau_of_DK: Chouser: The code is fantastic (I'd love to see those Python boys try to keep up) but I'm also most impressed by the approach you took, I cant really see myself coming to that solution anytime soon :)

14:16 AWizzArd: Chouser: your function is extremly fast, but the problem is that it does not produce a result.

14:17 Lau_of_DK: AWizzArd: details details

14:17 AWizzArd: (time (find-factors3 600851475143)) ==> []

14:17 but it should be [71 839 1471 6857 59569 104441 486847]

14:17 blackdog: i think you have to dorun or something AWizzArd ?

14:17 time won't force the laziness

14:18 AWizzArd: but the result should be printed on the repl

14:18 Lau_of_DK: Boss "Chouser, how can we optimize this computation?" Chouser: "Well boss, if we remove the computations, we will have increased performance by a gazillion"

14:18 Chousuke: with long it works

14:18 but there's no performance improvement

14:20 Chouser: AWizzArd: ah, details.

14:20 Chousuke: might be the quot/rem :/

14:21 AWizzArd: how?

14:21 Chousuke: maybe they're reboxing the numbers?

14:21 AWizzArd: yes strange, with long it works.. although it runs very slow again

14:21 Chouser: AWizzArd: yep, you're absolutely right -- I jumped the gun posting that. sorry.

14:22 AWizzArd: 100x more runtime than the java prog

14:23 Chousuke: a profiler would be useful I guess :p

14:31 Chouser: (/ (float n) i) appears to be a bit faster than (quot n i)

14:35 Chousuke: hmm

14:37 arohner: is there any reason why fns don't have metadata?

14:40 AWizzArd: Well Java (and unfortunately even Javasrcipt) easily outperform Clojure :-(

14:40 RSchulz: arohner: One guess would be that there isn't a good place to attach it.

14:41 Actually, I take that back. As Java instances, there would be an obvious place to attach them.

14:41 So it must be something else.

14:41 AWizzArd: yes

14:43 RSchulz: AWizzArd: Have you subscribed to Bill Clementson's Clojure-scanning Yahoo! Pipe?

14:44 I was reading through the posts, and found an interesting paper (that I've yet to read) from the JFP about computing primes functionally.

14:44 hoeck: AWizzArd: there is no primitive operation for rem in clojure.lang.Numbers

14:44 at least i didn't found one

14:44 AWizzArd: not subscribed

14:45 RSchulz: "The Genuine Sieve of Eratosthenes": http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

14:45 AWizzArd: I don't really need this function. I just saw a posting in another newsgroup about it, and saw how fast Lisp, Javascript and Java are. Now I wanted to give Clojure a try. It is very much slower when I write the code in a natural (clojurish) way.

14:46 hoeck: so the loop in find-factorial2 uses always slow boxed Numbers, no matter how hard you hint them :(

14:46 kotarak: arohner: there were previous discussions on this, eg. http://tinyurl.com/6om75n, maybe you should search on the list for more info

14:47 AWizzArd: maybe rhickey has some ingenious suggestion

14:53 Chousuke: hmm

14:53 I did some quick profiling

14:54 half of the time is spent in quot and rem, but var.get() is shown using 10% of the time as well :/

14:55 it keeps converting them to bigints :/

14:55 AWizzArd: I would expect that rem runs very often. But if it is mapped to Javas %...

14:57 So far still my find-factors2 performs best on my system.

14:58 But the factor of 50x between the Java and Clojure version is a bit unfortunate

14:58 RSchulz: What does this mean:

14:59 1:79 user=> (find-factors2 43587438757)

14:59 [21517]

15:00 AWizzArd: Do you know about any other factor in that number?

15:00 RSchulz: I just mashed the numeric pad!

15:00 AWizzArd: :-)

15:00 Well, then it is the only factor in that number

15:01 RSchulz: I don't think so!

15:01 AWizzArd: yes, my other implementations in Java and Lisp produce the same output

15:01 Well, maybe I have an error in all three implementations then.

15:01 RSchulz: 50620> factor 43587438757687

15:01 43587438757687: 11 3962494432517

15:02 (the 50620 is my command prompt)

15:02 (I set the history save count in my shell to 50,000...)

15:02 AWizzArd: Although we should keep in mind that humans are not very good in estimating if this list of factors is complete or not.

15:03 duck1123: Has anyone here done much with gen-class? I still can't figure this out, and I don't know what I'm missing.

15:03 kotarak: duck1123: what problem do you have?

15:03 lisppaste8: duck1123 pasted "attempt to create a servlet with gen-class" at http://paste.lisp.org/display/71768

15:03 RSchulz: 1:81 user=> (* 3962494432517 11)

15:03 43587438757687

15:04 So I think there's something amiss with find-factors2.

15:04 duck1123: kotarak: Tomcat isn't loading this class, and I haven't been able to decompile it

15:04 AWizzArd: RSchulz: I just hacked in a random number: 237583257239

15:05 my find-factors2 did not find any

15:05 funnily http://www.numberempire.com/primenumbers.php told me that this number is indeed a prime :-)

15:05 RSchulz: That one's prime.

15:05 50621> factor 237583257239

15:05 237583257239: 237583257239

15:06 kotarak: duck1123: is doGet static?

15:06 duck1123: no

15:07 RSchulz: AWizzArd: If you have access to Linux or Gnu tools otherwise, the factor command can serve to help you test your code's correctness.

15:07 duck1123: protected void

15:07 kotarak: duck1123: Then the first thing the function gets, is the instance itself: this.

15:08 AWizzArd: RSchulz: thx.. right now I am unfortunately under Windows. But later I will have Ubuntu again

15:08 RSchulz: You can (and _should_!) install Cygwin to get allmost all of the virtue of Linux on Windows.

15:08 http://cygwin.com/

15:08 duck1123: ok. So do I have to use :state, or will adding a this to the fn signature be enough?

15:08 kotarak: duck1123: Just add the this.

15:09 Chousuke: There are half a million calls to toBigInteger even if I give type hints and try to coerce everything to a bigint beforehand :/

15:09 kotarak: duck1123: Is this println always returning the out you call the method on? -> means (.println (.println (.println out ...) ..)..)

15:09 RSchulz: The factor command also differs from your example on the paste.list.org page.

15:09 kotarak: duck1123: maybe doto is what we need here.

15:09 RSchulz: factor 600851475143

15:09 600851475143: 71 839 1471 6857

15:10 1:83 user=> (* 71 839 1471 6857 59569 104441 486847)

15:10 1819914398210038019373933409

15:10 danlarkin: blackdog: clojure-json updated with a parser

15:10 lisppaste8: kotarak annotated #71768 with "Slightly modifid for duck1123" at http://paste.lisp.org/display/71768#1

15:10 duck1123: kotarak: you might be right, but I wasn't even getting that far

15:11 blackdog: ah, thanks danlarkin - i still didn't get time to try your last update

15:11 kotarak: duck1123: but with your tomcat problem: maybe you have to provide a special constructor?

15:11 AWizzArd: RSchulz: but (rem 600851475143 486847) ==> 0

15:11 kotarak: I don't have this Servlet stuff is created.

15:11 s/have/know/

15:11 AWizzArd: so 486847 really is a factor of that big number

15:11 blackdog: will try this evening

15:12 RSchulz: Yes, but 486847 isn't prime!

15:12 I did understand you to be trying to find a _prime_ factorization, right?

15:13 AWizzArd: RSchulz: I don't really care for what this function finds. I just found it in a posting in some other newsgroup, where they compared the runtime speed. So, I translated it to Clojure.

15:14 duck1123: I wasn't doing any special work in the constructor, and the super doesn't take any args

15:14 RSchulz: Ah. Sorry. Where did you find it? Which newsgroup?

15:14 AWizzArd: Whatever it finds, it's okay and not important for me. Only that Javascript perfroms dramatically much better than Clojure is what I find strange.

15:14 Chousuke: it seems CPU time is dominated by biginteger conversions :/

15:14 AWizzArd: RSchulz: c.l.l

15:14 Chousuke: for whatever reason.

15:14 RSchulz: comp.lang.lisp?

15:14 AWizzArd: yes

15:14 RSchulz: Circa? Subject? (I wanna' look it up.)

15:15 kotarak: duck1123: I'm sorry. Then I'm off. The code looks reasonable. I don't have experience with Java or Tomcat.

15:15 danlarkin: blackdog: I changed the way adding custom encoders works, it's now wrapped in a macro so you don't have to deal with namespace issues

15:15 duck1123: kotarak: thanks for trying

15:15 blackdog: danlarkin, once I fix the big i'm on i'll try it out :)

15:15 bug

15:16 AWizzArd: RSchulz: Message-ID: <0289a918-e694-419b-a697-f2133dfe3d97@j11g2000yqg.googlegroups.com>

15:16 kotarak: duck1123: One small thing: you named the class in lowercase. Maybe java is picky on this. Just guess, though...

15:16 RSchulz: Thanks.

15:16 What kind of link is that?

15:16 I'm getting "mailto:"

15:17 AWizzArd: it is the message id

15:18 Well, you can use the advanced search in google groups and just paste the message id there. They will point you to the right posting.

15:36 rzezeski: is there a way to attach a file to a google group post?

15:38 Chouser: you can if you send it in via email

15:44 rzezeski: Chouser, I just added a reply on the count problem. Did you look at that anymore today?

15:45 Chouser: I'm reading your reply. I've not done anything else with it today.

15:45 I guess I'm hoping for rhickey to weigh in on it.

15:46 rzezeski: me too

15:47 I'm going to keep looking at the source, but I think Clojure's creator would come up with something a lot better than my naive fixes

15:48 Chouser: rzezeski: I agree with your latest post. But the patch should not be for all ASeq

15:49 RSchulz: Chousuke, AWizzArd: I wonder if Rich would be amenable to creating a Clojure counterpart to TRUNCATE so the quotient and remainder can be retrieved with a single call.

15:49 Chouser: PersistentList implements ASeq, so would use this implementation, but PersitentList has it's own constant-time count() method

15:49 rzezeski: It seems count is used a fair amount internally in Clojure? If I put a system out in there I see it called quite a lot. I would really need to understand how count is used by the system to come up with something I could be half-confident in

15:49 Chouser: LazyCons may be too narrow, but ASeq is definitely too broad.

15:50 duck1123: is it possible to tell gen-class to not re-implement some of the non-private methods of it's superclass?

15:50 rzezeski: Yea, doing it for all ASeq was a naive decision, not something I gave any thought to

15:52 Chouser: duck1123: not that I know of. why would you want that?

15:52 rzezeski: Chouser: Also, maybe instead of a big if/elseif series maybe the method should be overloaded. One for non-lazy, another for lazy?

15:52 duck1123: I'm not overriding those methods

15:53 Chouser: duck1123: is there some harm it letting it implement them?

15:54 duck1123: I wrote pretty much the same thing in both clojure and java. The java version works while the clojure version does not.

15:54 Chouser: and you think the default re-implementations are to blame?

15:54 duck1123: looking at the decompiled class, the clojure version shows all of the fns, while the java version only showss what I've implemented

15:55 Chouser: that's what I'm thinking now... just grasping at straws

15:56 Chouser: ok. the reason behind the default implementations, I think, is it allows you to override any of them later without recompiling.

15:56 duck1123: the javadoc for the base class says that you shouldn't reimplement some of these fns

15:56 Chouser: will it by default call the base classes version?

15:57 or do I need to do that myself?

15:58 Chouser: i think it does that for you (unless you're extending an Interface), but I'm not seeing that in the docs

15:58 oh, here it is

15:59 "At runtime, a call to some method foo of the generated class will find the current value of the var implementing.namespace/prefixfoo and call it. If the var is not bound or nil, it will call the superclass method, or if an interface method, generate an UnsupportedOperationException."

16:02 duck1123: so this should work... do I need to provide a state object to handle the internal state?

16:03 Chouser: only if you have internal state to handle.

16:03 this is a servlet for tomcat?

16:03 duck1123: yes

16:04 I'm working with javax.servlet.http.HttpServlet

16:04 arohner: user=> (load "tutorial")

16:04 nil

16:04 user=> (require "tutorial")

16:04 java.lang.IllegalArgumentException: Don't know how to create ISeq from: Character (NO_SOURCE_FILE:0)

16:04 Chouser: duck1123: and you're generating .class files but getting errors when you start tomcat?

16:04 arohner: that indicates a problem with my ns, right?

16:05 duck1123: Chouser: I'm not getting any errors. Just a 404 when I try to load the page

16:05 arohner: (require 'tutorial)

16:06 arohner: duck1123: ah, thanks

16:06 user=> (compile 'tutorial)

16:06 java.io.IOException: No such file or directory (tutorial.clj:1)

16:06 Chouser: duck1123: bleh. nothing in a log anywhere?

16:06 duck1123: Chouser: I wish... That would at least give me something to go off of

16:07 AWizzArd: RSchulz: well yes, a truncate that returns a list of those two guys could be helpful

16:08 Chouser: Other have posted servlets created using gen-class from the pre-AOT days -- have you looked at any of these?

16:08 duck1123: no. Do you happen to know where those would be. I've found things using proxy, but not gen-class

16:09 drewolson: arohner: is . in your classpath?

16:09 arohner: yes. That bug was because the directory pointed at by *compile-path* did not exist

16:09 drewolson: gotcha

16:09 arohner: now I get: user=> (compile 'tutorial)

16:09 java.lang.RuntimeException: java.lang.ClassNotFoundException: tutorial$_now__90 (NO_SOURCE_FILE:0)

16:10 drewolson: arohner: *compile-path* also needs to be in the classpath

16:10 arohner: that makes sense. :-)

16:10 thanks

16:10 Chouser: duck1123: well, there's this, but you've probably passed this stage already: http://clj-me.blogspot.com/2008/06/how-to-genclass-servlet.html

16:10 drewolson: np

16:11 Chouser: duck1123: http://groups.google.com/group/clojure/browse_thread/thread/c68d2d8566134847

16:16 duck1123: Chouser: that is surprisingly similar to what I have

16:17 Chouser: any useful differences (other than pre/post AOT stuff)?

16:18 duck1123: not that I can see

16:18 arohner: if you use gen-class with a state field, how does an instance method of the class refer to its own state?

16:18 duck1123: javap is giving me this line. does this make any sense to you: public static {};


16:19 Chouser: arohner: usually (.state this)

16:19 arohner: ok, cool. I didn't know "this" was defined

16:19 Chouser: arohner: it's not

16:19 :-)

16:19 I suppose you want more detail...

16:20 arohner: yeah... :-)

16:21 Chouser: (.state this), assuming you named your state 'state' by saying ":state state" in your ns macro, and that the first arg of your method defn is named 'this'

16:23 arohner: oh, so the first argument in your methods are to the 'this' object?

16:25 nevermind, I get it

16:25 Chouser: arohner: yes, for gen-class. That's different than proxy which binds the word 'this' for you.

16:25 arohner: Chouser: thanks

16:26 though it's weird that my methods appear to work, taking no arguments

16:57 Lau_of_DK: (defn query

16:57 [& keys]

16:57 (let [sel (:select keys)

16:57 table (:from keys)]

16:57 (println sel)

16:57 (println table)))

16:57 Why does (query :select * :from table1) output 2x nil

17:18 hiredman: Lau_of_DK: that is not a hash

17:18 (:select 'not_a_hash) -> nil

17:18 Lau_of_DK: Yea I worked it out, thanks anyway

18:49 Kerris7: I always thought that I have a reasonable degree of tolerance towards verbosity, but Clojure has really been whittling that down to the point that I'm starting to pine for Clojure whenever I'm ask to write anything in Java for schoolwork. :(

18:50 kotarak: (-> (var print-method) meta :ns ns-name name) Where have all the parens gone?

18:55 arohner: so (struct-map wants args in the format (struct-map my-struct :a a-val :b b-val :c c-val)

18:55 I have a map that is {:a a-val :b b-val :c c-val}

18:55 how do I pass that to struct map?

18:56 kotarak: not tested: (apply struct-map (mapcat identity your-map))

18:56 with the struct inbetween of course

18:57 arohner: ah, mapcat

18:57 hiredman: (doc struct-map)

18:57 clojurebot: Returns a new structmap instance with the keys of the structure-basis. keyvals may contain all, some or none of the basis keys - where values are not supplied they will default to nil. keyvals can also contain keys not in the basis.; arglists ([s & inits])

18:57 arohner: kotarak: thanks

18:57 rhickey_: user=> (apply concat {:a 1 :b 2})

18:57 (:a 1 :b 2)

18:59 arohner: rhickey: thanks

19:08 powr-toc: What's the name of the function that'll turn '(\s \t \r \i \n \g) into a "string"? I can't seem to find it..

19:09 kotarak: (apply str '(\s \t ...))

19:09 powr-toc: ahh yeah... thanks! :-)

19:09 AWizzArd: rhickey: do you have an idea on how to make this perform better? http://paste.lisp.org/display/71753

19:10 rhickey_: currently still find-factors2 performs best, but still very much slower than the Java code.

19:11 RSchulz: AWizzArd: Ask rhickey about a Clojure counterpart for CL FACTOR...

19:11 Oops!

19:11 AWizzArd: truncate you mean?

19:11 RSchulz: I meant TRUNCAT, not FACTOR!


19:11 ...Can't type. Can't think.

19:11 AWizzArd: hehe, a factor function would be nice though ;-)

19:11 a bit cheating *g*

19:12 RSchulz: That's your hobby-horse...

19:13 We could ask for a quantum-computer Clojure, while we're at it. They're supposed to be good at factoring.

19:16 AWizzArd: but then Javascript can maybe also use them

19:23 RSchulz: an unchecked truncate...

19:24 (unchecked-truncate num div)

19:32 danlarkin: ugh I'm so bad at writing documentation

19:33 lisppaste8: AWizzArd pasted "Improved find-factors, still factor of 10x slower" at http://paste.lisp.org/display/71780

19:35 AWizzArd: I think this new version leaves at least Javascript behind :-)

19:41 RSchulz: On my system, the time for the given test case drops from about 1.4 mSec to about 1 mSec.

19:42 AWizzArd: wtf.. what cpu do you have? :-)

19:42 RSchulz: danlarkin: Many programmers are, but... It seems a bit of a non-sequitur...

19:42 AWizzArd: Pentium 4 HT 3.0 GHz.

19:43 If it _really_ mattered, I could set up on my Core2 Duo (2.7 GHz) and test there.

19:43 AWizzArd: would be nice to see that

19:43 RSchulz: But I've gotta' say, my experience has been that memory throughput is _far_ more significant than CPU speed!

19:43 AWizzArd: I am on a Core 2, T7600 @ 2,33 GHz

19:43 hiredman: mmm

19:43 Chousuke: I ran that on my 2.16GHz c2d and got 962ms

19:44 oh. interesting

19:44 RSchulz: hiredman: Care to elaborate?

19:44 hiredman: my c2d gets 439.493011 msecs

19:44 Chousuke: inc is actually faster than unchecked-inc :P

19:44 AWizzArd: It's a core 2 that I have, but not due.

19:44 duo

19:44 RSchulz: Well, we're all jealous of hiredman...

19:44 hiredman: RSchulz: core 2 duos

19:45 RSchulz: But, if I may say so, I'm guessing I could best that on my Core2 Duo box.

19:45 AWizzArd: well, my Thinkpad was extremly expensive, but RSchulz' system runs much faster. Nice.

19:45 RSchulz: But I can't do that in just a few minutes.

19:45 AWizzArd: maybe tomorrow?

19:45 RSchulz: I have no Clojure set-up there.

19:45 AWizzArd: RSchulz: a computer can only be good when it has a Clojure setup

19:45 hiredman: my c2d is a 2.13

19:46 AWizzArd: Uh!

19:46 RSchulz: I usually see about 2:1 improvement on my Core2 Duo system. But that's not my primary development machine.

19:46 AWizzArd: hiredman: and how fast is the pure java code then on your machine?

19:46 hiredman: ugh

19:46 I dunno

19:46 * hiredman tries to remember how to do java stuff

19:46 RSchulz: Java? What's that??

19:47 Blub?

19:47 I love that name...

19:47 AWizzArd: hiredman: just copy+paste my java example and do a javac Factor.java on it

19:47 then java -server Factor

19:47 danlarkin: RSchulz: looks like I'll just be copying and pasting some REPL interaction :)

19:47 hiredman: ah

19:47 I am not using -server

19:47 AWizzArd: but on your fast machines you will probably need to replace System.currentTimeMillis(); with System.nanoTime();

19:47 RSchulz: You've gotta' be care with the -server stuff. It makes it take a lot longer to "warm up." even if it's better after that.

19:48 hiredman: ugh

19:48 AWizzArd: RSchulz: see the java code.. it does the measuring after startup

19:48 hiredman: with -server the clojure time almost doubles

19:48 AWizzArd: http://paste.lisp.org/display/71780

19:48 hiredman: ah, that was some kind of outlier

19:48 AWizzArd: hiredman: run it inside a repl and use Clojures (time ...)

19:48 hiredman: settled back down after a few runs

19:48 RSchulz: hiredman: That's not surprising, but I'd expect that after a longer warm-up time, the differences would come down.

19:49 hiredman: heh

19:49 AWizzArd: RSchulz: can you plesae try the java code from the paste?

19:49 hiredman: the java version was 93msecs

19:49 RSchulz: Clojure (and Scala) and other functional / closure-oriented languages make things hard on the JIT compiler.

19:49 AWizzArd: Sure. 71780?

19:49 AWizzArd: Just paste it into Factor.java and compile it with javac Factor.java and run it with java -server Factor

19:49 yes

19:49 71780

19:49 RSchulz: Today's winding down, but I'll do it first thing tomorrow.

19:50 AWizzArd: but currentTimeMillis is maybe not enough for your fast system anymore

19:50 hiredman: I tried have the clojure code just print out the factors, which is what the java does, instead of using conj, but that seemed to make it run slower

19:50 AWizzArd: you will probably need to replace System.currentTimeMillis(); with System.nanoTime();

19:50 RSchulz: OK. I'll use the high-resolution clock.

19:50 AWizzArd: hiredman: yes, printing takes more time

19:51 RSchulz: It's best to exclude I/O and formatting from the measurement, obviously.

19:51 hiredman: uh

19:51 AWizzArd: so, in this regard the Clojure code is cheating a little bit

19:51 hiredman: with nanotime the java code claims to have run in negative time

19:51 msecs: -6468186240258

19:51 RSchulz: Woo-Hoo!

19:51 Chousuke: :p

19:51 RSchulz: Next stop, time travel!

19:51 Chousuke: what kind of code does the clojure function compile into? :/

19:52 maybe it does a lot of small allocations

19:52 many* even...

19:52 hiredman: ah, I id not change the second time call

19:52 RSchulz: Does anybody remember the Apple Mac Tech Note about the "Subspace Transceiver?"

19:52 You've got to be "of a certain age" to have been around then...

19:53 AWizzArd: hiredman: there were two calls to Milis

19:53 hiredman: when dinosaurs walked the earth

19:53 RSchulz: Now, now...

19:53 hiredman: the number printed is in nanoseconds now too

19:53 AWizzArd: you probably replaced only the first one, so that you substracted a huge number from a small one

19:54 that would explain your negative number

19:54 RSchulz: I wonder if Clojure will benefit from escape-analysis-based allocation optimization?

19:54 AWizzArd: RSchulz: have you already tried the .java code?

19:55 hiredman: so nanotime gives 50 msecs

19:55 I using jdk7 btw

19:55 AWizzArd: inside a server vm?

19:56 hiredman: actually it seems to bounce between 80msecs, 40, and 50

19:56 RSchulz: Uh, no. I have to set up Clojure on my fast machine, first.

19:56 AWizzArd: RSchulz: i mean on your current one

19:56 your machine now ran the clojure code in just 2 msecs?

19:56 RSchulz: JDK 7? What's included / new in that release?

19:57 AWizzArd: hiredman: and how fast again is the clojure find-factors for you?

19:57 hiredman: it runs on my c2d, which previouse releases would not

19:58 lowest run I see is around 250msecs

19:58 er

19:58 430

19:59 AWizzArd: how can it be that it runs in 1 msec on RSchulz' machine?

19:59 RSchulz: OK, AWizzArd: On my workaday machine, a simple compilation and invocatin of Factor gives 119 mSec.

19:59 When did I say that??

19:59 AWizzArd: his box can't be 100x faster no?

20:00 RSchulz: By the way, that was using the Java 1.5 JVM.

20:00 AWizzArd: (01:38:41) RSchulz: On my system, the time for the given test case drops from about 1.4 mSec to about 1 mSec.

20:01 RSchulz: Are we talkingn about class Factor show on paste.lisp.org 71780?

20:01 AWizzArd: yes

20:02 My timings are inclueded here: http://paste.lisp.org/display/71780

20:02 clojure 376 milliseconds, java 29 milliseconds, both running in a -server

20:02 RSchulz: 70 mSec on my Core2 Duo.

20:03 AWizzArd: for the clj version, yes?

20:03 RSchulz: Ranging from 43 to 89.

20:03 Java version.

20:03 I don't have Clojure set up on that machine.

20:03 AWizzArd: ah oki

20:04 Thanks for the tests. Maybe rhickey still has an idea if we forgot a little type hint or something like that. I need to run, night night

20:05 RSchulz: Ah! When I switch the CPU frequency policy from "dynamic" to "performance", the times shift down into the 40 - 50 mSec range.

20:06 * AWizzArd did that too

20:06 AWizzArd: n8

20:06 RSchulz: Ciao~!

20:48 clojurebot: svn rev 1147; added unchecked-remainder

20:50 rhickey_: find-factors with unchecked ops: http://paste.lisp.org/display/71753#2

20:58 RSchulz: I get 109 mSec on my first invocation of (time (find-factors 600851475143))

20:58 The times repeatedly center within several percent of 110 mSec.

20:58 * Chousuke goes and reclones the clojure SVN

20:59 Chousuke: the git mirror is too laggy :/

20:59 RSchulz: rhickey_: What is changed in 1147?

21:00 hiredman: accoding to clojure bot, he added unchecked-remainder :)

21:00 clojurebot: botsnack

21:00 clojurebot: thanks; that was delicious. (nom nom nom)

21:00 Chousuke: too bad SVN checkouts are so slow; I guess I'll just go to sleep and it'll be ready in the morning :P

21:00 RSchulz: Bah! What does clojurebot know! He's just a bot.

21:00 Chousuke: but he's written in clojure

21:01 clojurebot: brain dump?

21:01 clojurebot: brain dump is http://clj.thelastcitadel.com/clojurebot

21:01 Chousuke: and that's what he knows.

21:01 RSchulz: I don't have any trouble getting quick SVN updates.

21:01 Chousuke: RSchulz: well, you're not checking out *every* revision

21:01 that's what git svn clone does.

21:01 RSchulz: I come close. I "svn up" at least once every day.

21:02 Chousuke: that's still not the same.

21:02 RSchulz: Why go the indirect route via git?

21:02 Chousuke: because git is much nicer to work with :P

21:02 git log for example does not require internet access

21:03 RSchulz: What's to be nice? I just want to get updates. I give one command ("svn up") and then build ("ant") and it's all over.

21:03 Chousuke: well, I do local edits sometimes.

21:03 It's nice to be able to commit those :P

21:03 abrooks: Chousuke: At least with git you can rebase easily. :)

21:04 RSchulz: OK. I know nothing about git, really.

21:04 Chousuke: and with the exception of the initial SVN checkouts (and the slowness is because of SVN, not git. :)), git is also faster than SVN at everything.

21:04 RSchulz: Sure, but half nothing is still nothing.

21:05 Chousuke: it's not "nothing" if you like to read the SVN logs from time to time like I do :p

21:05 emacsen: pjb3, I feel so dumb. I didn't say hi to you today

21:05 Chousuke: or if you do local edits.

21:05 emacsen: I was a bit overwhelmed with something I had to do afterwards

21:05 Chousuke: it seems my internet connection has somehow stalled now.

21:06 it's not getting any more stuff from the SVN repo :(

21:06 RSchulz: But if it's faster, why do you say "SVN checkouts are so slow?"

21:06 Chousuke: that's because they are

21:06 native git clones are not

21:06 of course, that depends on the size of the repo I guess

21:06 RSchulz: But I got 1147, built and tested without any delay. Faster than I could type, basically.

21:07 Chousuke: git repos contain all of the history.

21:07 RSchulz: OK, but does that matter? Do you use that history?

21:07 Chousuke: so to clone an SVN repository into a git one, you need to checkout every revision initially.

21:08 updates are of course just checking out what changed

21:09 I suppose I could make a git repo out of just the most recent checkout but I don't know a straightforward way to do that

21:09 git svn clone defaults to getting everything it can

21:09 RSchulz: Or you could just access the SVN repository...

21:09 Chousuke: nah, I don't want to use SVN

21:09 RSchulz: Suit yourself!

21:09 Chousuke: with git I at least have local commmits.

21:12 meh, it's not going any further it seems

21:13 pjb3: emacsen: nope problem, you were the guy talking about HacDC, right?

21:13 Chousuke: but hm, I just found something from the docs that should allow me to "retrack" the clojure SVN using a git repo based on one of the github mirrors

21:13 emacsen: yup

21:13 Chouser: Whoa. Clojure grew a 'while' macro.

21:13 arohner: ?

21:14 Chouser: (doc while)

21:14 clojurebot: Repeatedly executes body while test expression is true. Presumes some side-effect will cause test to become false/nil. Returns nil; arglists ([test & body])

21:14 Chouser: it's a week and a half old, but I didn't notice it going in.

21:15 emacsen: pjb3, I also have auditory processing difficulties and so the whole bar thing wasn't working for me

21:15 but I'd be just as happy if we went to Reiters

21:15 if they'd have us

21:15 and we could project

21:15 arohner: if I have a defstruct, is there a way to see what keys it has, without creating a new instance?

21:20 Chouser: Don't tell anyone I told you.

21:20 (.get (first (.getDeclaredFields (class x))) x)

21:21 If you meant "a support way," I think the answer is currently: no.

21:21 supported

21:31 abrooks: Hm. The addition of while makes me hungry for a while-let.

21:32 I've sort of wondered why all the *-let functions aren't just folded into their primaryies and detected by a first argument vector.

21:33 Chouser: ooh!

21:33 abrooks: There's the response I was looking for. :)

21:34 Garsh. s/primaryies/primaries/g

21:34 Chouser: It might be pretty surprising when a particular construct doesn't interpret the vector the way you expected.

21:35 the non-existance of 'while-let' is a bit clearer than your (while [x (foo)] ...) being and unexpected infinite loop.

21:35 s/and/an/

21:36 abrooks: If we set a precedent I don't think it would be unexpected.

21:37 Most (all?) of the body taking forms want both binding and non-binding versions.

21:38 Why not just make the precedent that body-taking forms have an optional binding argument.

21:38 A bare vector in a body is meaningless otherwise.

21:41 Chouser: abrooks: you're referring to macros like 'do', 'delay', 'doseq'?

21:42 these all take bodies, but I have no idea what a binding macro would be used for.

21:42 s/macro/vector/

21:42 abrooks: abrooks: Yes. do with a binding would avoid having (let [] (do ...)) -> (do [] ...)

21:43 Chouser: let already has an implicit do

21:43 abrooks: delay is probably not so useful but I suppose you could include it and have the binding run delayed -- might be handy)

21:43 Chouser: let is lazy.

21:43 * Chouser blinks

21:43 abrooks: Chouser: doseq already has a binding form.

21:43 Chouser: Uh... (do ) is eager, right??

21:44 Chouser: what it the world are you talking about?

21:44 in

21:44 why cant I type???

21:47 abrooks: Chouser: Not sure... let is eager for the non-terminal slots of course.

21:48 I guess let and do are fully equivalent modulo the binding.

21:52 Chouser: each expression in the body of 'let' is evaluated.

22:00 lisppaste8: powrtoc pasted "Permutations" at http://paste.lisp.org/display/71785

22:01 Chouser: java.lang.Exception: Unable to resolve symbol: anagram in this context (NO_SOURCE_FILE:34)

22:02 lisppaste8: powrtoc annotated #71785 with "typo fix" at http://paste.lisp.org/display/71785#1

22:03 Chouser: powr-toc: neat.

22:03 powr-toc: I implemented permutations based on the implementation in the "programming erlang" book... Using a list comprehension... It appears to be faster than the implementation in clojure contrib too.

22:04 Chouser: I believe the one in clojure.contrib can handle identical items in the seq.

22:04 powr-toc: ahhh

22:06 Chouser: powr-toc: compare/contrast with http://paste.lisp.org/display/70662

22:07 powr-toc: Chouser: no, I don't think the implementation in contrib does handle identical items...

22:08 user=> (permutations "aaa")

22:08 ((\a \a \a) (\a \a \a) (\a \a \a) (\a \a \a) (\a \a \a) (\a \a \a))

22:08 user=>

22:09 Chouser: Isn't that correct?

22:14 powr-toc: Yes, it is... I thought you meant something different by identical items...

22:15 Chouser: the implementation I pastied should handle identical items too

22:18 Chouser: Hm, I guess it might be accurate to say both fail in different ways.

22:19 powr-toc: Chouser: in what way does my implementation fail?

22:19 Chouser: it seems like 112 ought to produce 112 121 211

22:22 powr-toc: ahh yeah, I see what you mean now... interesting

22:24 hmm.. I guess that's the problem with using filter...

22:27 Chouser: but there are plenty of cases where you don't need to handle duplicate items

22:28 powr-toc: true

Logging service provided by n01se.net