#clojure log - Jun 20 2008

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

1:54 Lau_of_DK: Morning folk

2:21 cgrand1: morning Mr Lau

5:49 Lau_of_DK: cgrand - Can you post the link to your blog again ?

6:22 cgrand: clj-me.blogspot.com

6:23 Still trying to find the first x! with 7^20 trailing 0s?

6:44 Lau_of_DK: cgrand - If you have one I'd love to hear it, Im thinking that maybe brute is not the best way to go

6:51 cgrand: when you define naturals like this (def naturals ((fn [x] (iterate inc x)) 1)) the thing to know is that all computed values will stay in memory

6:54 that explains why you run out of memory with the code you pasted

6:58 plus, you are testing all the naturals til you found the first natural wich can be divided by 10^(7^20), which even if you test 10^9 numbers by second would take 10^(7^20-3) seconds to run...

7:01 Lau_of_DK: yea, so youre saying its a dumb approach which is exponential in time consumption?

7:01 smee: hey

7:02 cgrand, how's your blogpost about parallelizing widefinder2 coming along?

7:08 cgrand: Lau_of_DK: no I think that brute force may work but you have forgotten to apply the factorial

7:11 smee: I hope to post something this afternoon (er.. I mean in the next hours) I played a lot with the server trying different implementations (the naive one to which I allude in the previous blog post works pretty well with a few cores (2-4) but not with 32 -- the bottleneck is shifting from CPU to IO) and resolving some GC problems

7:16 smee: cgrand: nice, thanks. looking forward to it, as the documentation of using the concurrency feats of clojure is quite sparse...

7:34 cgrand: Lau_of_DK: hmm after some trials, I was wrong: brute force won't cut

7:37 lisppaste8: cgrand annotated #62507 with "Brute force does not work :-(" at http://paste.lisp.org/display/62507#1

7:40 Lau_of_DK: cgrand, ok, thanks for looking into it

7:41 I actually think that theres a pattern emergin in the number of trails

10:29 cgrand: rhickey: from the main thread I send an action to agent A, in this action I send an action to agent B. After awaiting A, on the main thread, I can await B. No?

10:43 rhickey: cgrand: you can await B, but there is no guarantee your wait request will follow A's send to B

10:48 cgrand: so I have to send a second action from A to B, which action would .countDown on a latch while the main thread await this latch or something like that?

10:49 rhickey: is there some context here that could help me understand what you are trying to do?

10:52 cgrand: ok

10:56 I have some workers (agents) which when they are done with their batch send the result to an accumulator agent. I want to know when the accumulator is done.

10:56 rhickey: does the accumulator know when it's done?

11:05 cgrand: no

11:08 rhickey: do only the distributor knows how much work was dispatched? does it know how many agents will be created to do the work?

11:08 or how much work there is, in advance?

11:09 you can either send a sentinel/shutdown job through or wait on a completion counter

11:10 cgrand: the distributor doesn't know how the amount of work in advance but it knows how many agents there are (it creates them)... so it's a sentinel in that case I guess

11:12 rhickey: the sentinel job can decrement a countdown latch

11:12 cgrand: ok

11:18 thanks, that what I was after.

11:25 But right now the await trick works, no? It's not clear for me which are the guarantees of the agents system. I thought that they ware: 1/ in order execution of all actions dispatched from one thread to one agent and 2/ when await returns, all actions dispatched from the awaited agent are enqueued in the target agents. So I suppose you don't guarantee the second point.

11:25 s/ware/were/

11:29 rhickey: right, point 2, while currently true, is not a guarantee. What is guaranteed is the order of actions sent A) from the same agent to a single agent, B) from the same thread to a single agent. An await is just another action. Message sends are technically asynchronous

11:30 if you were to build on the fact that a's sends were queued before a returned, then your architecture would break as soon as b's started delegating to c's

11:30 i.e. the trick only works for one hop

11:31 cgrand: yup

11:32 rhickey: await is just for the simplest cases - queues and latches are the right way to do workflow, and Java has a good suite

11:35 cgrand: ok -- I'm doing some cleaning on my wf2 implementations

11:36 btw why is butlast eager?

11:43 rhickey: no good reason, probably because I needed it for defn and just hacked last

11:49 cgrand: Ah, ok.

11:49 Am I wrong thinking you are cleaning locals before tail call?

11:50 rhickey: yes, I'm clearing locals on tail call

11:53 drewr: After evaluating (def foo 1) (def foo 2), what happens to the first object foo was pointing at? I'm assuming it gets garbage collected?

11:53 rhickey: drewr: yes

11:54 drewr: ...assuming nothing else is reading it I guess.

11:58 cgrand: and on a "tail loop" as well?

12:00 rhickey: no, since the body might need them again, but of course the loop 'args' are replaced by the new values

12:05 drewr: Wow, jochu's been busy.

12:05 swank-clojure now has sldb support.

12:56 How do I kill a thread that I SEND-OFFed?

12:57 rhickey: killing threads is generally bad practice - what is it busy doing?

12:57 drewr: Querying a database.

12:58 I didn't give my query a sufficient WHERE clause to keep it from running for way to long.

12:58 too

12:58 rhickey: can you break the db connection?

12:59 drewr: Ah, (.close *conn*) did the trick.

12:59 Then my agent got SQLException. Nice.

13:00 So what happens to old agents, they just get GC'ed too?

13:00 rhickey: GC is pervasive - things no longer referenced get GCed eventually

13:01 but yes, there is no registry of agents to clean up

13:02 drewr: Right, I was making sure there wasn't a Clojure-y thing I needed to do to say I was done with it.

13:40 Lau_of_DK: Evening Gents

13:43 drewr: Yo.

13:56 meredydd: Hey, rhickey

13:56 rhickey: hi

13:56 meredydd: In the 'set namespace under what conditions does (join) return nil?

13:56 I was expecting an empty relation (#{})

13:58 It seems to be "when one of the relations is empty"

13:58 (join #{{:a 0 :b 1}} #{{:a 1 :c 2}}) gives an empty set; (join #{{:a 0 :b 1}} #{}) gives nil

13:59 rhickey: I see

14:00 meredydd: Ah...you have a "(when (and (seq xrel) (seq yrel)))"

14:00 rhickey: fixing now, hang tight...

14:00 meredydd: ta

14:04 rhickey: I've made that return an empty set for now, but wonder if both cases shouldn't return nil...

14:06 meredydd: As I see it, if you're looking for a faithful representation of the relational algebra, the empty set is the mathematically correct thing to have

14:07 Lau_of_DK: how is that more correct than nil?

14:07 meredydd: Lau_of_DK: You can (conj) onto it, for starters

14:07 rhickey: if you end up with a lot of (if (zero? (count result)... then I disagree

14:07 this is a Lisp with a CL bent in this area

14:08 meredydd: I agree entirely on the subject of convenience

14:08 (I'm doing (= best-match #{}) myself)

14:08 rhickey: there you go :)

14:08 meredydd: To be honest, a little bit of me secretly wishes that all the empty collections were logical "false" values

14:09 But I feel profoundly uncomfortable with a (join) operation that isn't guaranteed to return a relation

14:10 rhickey: that would be a reduction in power, since the current strategy gives you the ability to distinguish the two

14:10 meredydd: Uh-huh - I understand why you did it.

14:10 (although one could also argue that even under the current scheme, you retain the ability to distinguish between 'false' and 'nil')

14:11 rhickey: I understand about the empty set, I think I returned that against my Lisp inclinations for fear of lack of composability in this algebra, although I don't know that that is the case

14:11 meredydd: Heh. It is definitely in mine - one of the next things I do to the return value is (conj) another map onto it

14:13 Lau_of_DK: I cant find this on the website, but what was the form from printing ints as either hex or binary

14:19 zzZZZ

14:20 meredydd: Eh-oh. I just pulled your latest from the repos, and the Repl now won't start.

14:20 rhickey: clean?

14:20 meredydd: Caused by: clojure.lang.Compiler$CompilerException: proxy.clj:52: clojure.lang.RT.cons(Ljava/lang/Object;Lclojure/lang/ISeq;)Lclojure/lang/ISeq;

14:20 oh, oops.

14:21 That worked.

14:21 Lau_of_DK: rhickey, after answering my binary question, maybe you should make a script to fetch the svn, clean up and compile, it seems to be a common pitfall

14:24 * meredydd vanishes

14:26 meredydd: rhickey: If you do change your mind on (join) behaviour (although I favour the #{} representation), could you drop a note to the Google Group? Fool that I am, I'm writing stuff on top of this functionality, so would appreciate the notice to go change things.

14:26 rhickey: leaving it where it is for now, will mention on group if changed

16:03 wwmorgan: (fn [[a & b]] (if (nil? a) 0 (recur b))) works for all vectors except []

16:03 should it throw an except when it gets passed []?

16:04 drewr: wwmorgan: Why [[a & b]] ?

16:05 wwmorgan: you mean instead of [coll] then let [[a & b] coll] ?

16:05 drewr: Are you trying to destructure a vector parameter?

16:06 wwmorgan: trying to destruct an seq-able parameter

16:07 vectors, strings, etc

16:14 drewr: I assume since A is a required param that [] should throw an exception.

16:15 wwmorgan: I thought the behavior was to set a to nil then?

16:15 because it works if you pass in nil but not []

16:19 I think it's because it calls nth and rest on the parameters

16:20 and (nth nil X) is nil for all X

16:20 hoeck: wwmorgan: yeah, and (nth [] 1) is an Exception

16:21 wwmorgan: right, although it's (nth [] 0) in this specific case

16:22 hoeck: or generally nth'ing on the empty vector

16:23 wwmorgan: but (first []) is nil

16:24 hoeck: yes, but it reads as (first (seq []))

16:24 it makes a seq 'view' on the vector

16:24 (get [] 0) returns also nil

16:25 wwmorgan: shouldn't sequential decomposition also read a seq view?

16:26 hoeck: it does, but only the b in [[a & b]]

16:26 wwmorgan: right, which is why the function above works for non-[] values

16:28 it looks like sequential decomposition calls nth instead of get

16:28 hoeck: exactly

16:28 wwmorgan: is this right or wrong?

16:29 hoeck: to use `get', just wrap (binding [nth get] ... ) around your function

16:30 wwmorgan: oh yeah, there are a few ways to do it

16:30 I guess this is more of a feature request

16:31 lisppaste8: Lau_of_DK pasted "Delayed execution" at http://paste.lisp.org/display/62570

16:32 Lau_of_DK: Gents - This little setup-ui implements 3 event listeners, on click, on property change, and on action. They all work, but only onClick outputs the result immediately, so if I change the property 3 times, and then click on the form, it outputs

16:32 changed

16:32 changed

16:32 changed

16:33 click

16:33 but I dont see the 3x changed, before I fire OnClick - Why is that ?

16:35 blackdog: i don't println to the stdout either, i didn't investigate but i use an alert instead (defn alert [mess]

16:35 (. JOptionPane showMessageDialog (Gget :frame) mess))

16:36 Lau_of_DK: oh, so its a stdout issue?

16:36 cause alert fires like it should

16:37 blackdog: yea, i think it's that, or maybe swing redirects stdout or something

16:37 don't know

16:37 if alert works i think it's all good, maybe use a logger instead of stdout

16:38 Lau_of_DK: Yea, alert works, so I'll simply implent the real event handlers

16:38 Its the firing time that mattered

16:38 cemerick: rhickey, hoeck: I think wwmorgan is right -- that's a bug. [] should destructure just as well as the empty list.

16:38 Lau_of_DK: Thanks alot Blackdog

16:38 blackdog: yw

16:38 cemerick: (let [[a & b] '()] 0) works but (let [[a & b] []] 0) doesn't.

16:39 Or, it's a bug at least insofar as I read the section on destructuring at http://clojure.org/special_forms

16:43 hoeck: cemerick: but the special-forms page mentions nth explicitly

16:45 cemerick: hoeck: that doesn't strike me as a problem. In this case, if 0 and 1 are illegal indices, then I would expect clojure to catch those exceptions and substitute nil so as to be congruent with how seqs are destructured.

16:45 hoeck: i have never used destructuring for traversing vectors, only to hold and destructure data, so that excepion was quite useful

16:45 cemerick: Otherwise, vector (and string) destructuring has these odd corner cases, and you really need to wrap everything going into a destructured let in a (seq ...)

16:46 hoeck: yeah, thats bad, especially when destructuring in a fn or defn (where you can't call seq)

16:48 cemerick: Right. It certainly seems like a straightforward problem (although I'm currently looking for my flak jacket for when Rich lands on me for making such pronouncements ;-)).

16:48 rhickey: I was just looking at this, destructuring seqs with nth. The docs and behavior match (it says it will use nth, and nth on vectors has that behavior), but I agree that get might be more useful

16:50 cemerick: rhickey: nth is used instead of get for performance?

16:51 hoeck: :or in vector/seq destruction would be usefull too!

16:54 rhickey: nth is potentially faster as it is just about indexed access, i.e. the key is known to be an int

16:55 cemerick: in any case Clojure is not going to catch exceptions in normal control flow

16:56 cemerick: rhickey: Sure, right.

16:56 rhickey: the tradeoff is a lack of 'arity' checking

16:56 which has utility for sequential destructuring

16:57 cemerick: rhickey: Isn't that true when destructuring a seq, though?

16:57 Nafai: rhickey: Watching your Clojure for Java programmers talk. Enjoying it so far.

16:57 rhickey: the real problem may be nth's different behavior for seqs

16:57 Nafai: great!

17:00 cemerick: Well, in any case, I'd certainly like to see destructuring "work" for all seqs, vectors, and strings. I think defaulting to nil is the right behaviour, and goes nicely along with default behaviour for (and), (+), etc.

17:24 rhickey: ok, SVN 915: nth takes an optional not-found value, and destructuring uses nth with a nil not -ound value for sequential destructuring, nth without not-found value throws exception in all index-out-of-bounds cases including seqs

19:09 Lau_of_DK: I have a function that supposed to resize an image in a swing gui, but instead of resizing it sounds the system bell, no warnings, no exceptions, nothing - How do I figure out whats firing the bell?

19:11 Im asking for a general approach - the specific problem doesnt matter

19:12 Chouser_: can you break it up into smaller pieces?

19:12 Lau_of_DK: Thats what I usally do, but it seems like the Flintstones approach

19:18 Chouser_: Hm. I must live in Bedrock.

19:19 Lau_of_DK: Dont be offended

19:19 I'm just used to Visual Studio : "Cast type exception thrown: main.cpp [line: 25;column:8]"

19:19 That speeds up development by about 1600% compared to splitting routines up

19:24 Chouser_: Does Visual Studio capture beeps? ;-)

19:26 Lau_of_DK: sure :)

19:27 But you get the point right? Bug-hunting could probably be simplied

19:33 Nevermind, I'll explain it tomorrow, sleep tight Chouser + the rest of the gang

Logging service provided by n01se.net