#clojure log - Feb 22 2009

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

0:25 digash`: attribute filtering is broken in xml.clj

0:25 not sure what the problem is

0:25 just broke with the new lazy patches

0:25 ; attribute filtering

0:25 (assert (= (xml-> atom1 :link [(attr= :rel "alternate")] (attr :type))

0:25 '("text/html")))

0:26 throws exception with NullPointer.

0:32 lisppaste8: digash` pasted "assert error in zip-filter" at http://paste.lisp.org/display/75949

0:32 blbrown: is there a formal way to report bugs. I am assuming emails the google groups is not always the best

2:55 te: 'lo

3:36 Lau_of_DK: Top of the morning gents

4:44 When I fire up gen-class with this arg :constructors {[String com.jme.scene.Node] []}) Doesnt that mean, that my class will require a String. and a Node. when constructed?

4:51 Ok - Better question, is there a java-call I can make to my class, which will show me the contructors requirements?

5:52 alinp: hi

5:52 is there a way to call "time" function from java env ?

5:53 and I don't mean by calling clojure env

5:53 time function have some java method/class associated ?

5:54 ~doc time

5:54 clojurebot: Gabh mo leithsc�al?

5:54 alinp: ,(doc time)

5:54 clojurebot: "([expr]); Evaluates expr and prints the time it took. Returns the value of expr."

6:47 Lau_of_DK: Why is it - That when I want to use an enumerator from a class, I have to use its fully qualified name ?, ie

6:47 (import '(com.jme.image Texture))

6:47 nil

6:47 com.jme.image.Texture$Enum1/field1

6:47 <value returned>

6:47 Texture$Enum1/field1

6:47 Exception

6:47 Why is that?

7:11 AWizzArd: Lau, after you did that import, what happens if you just type Texture in the repl?

7:26 Chouser: (import '(com.jme.image Texture$Enum1))

7:35 AWizzArd: btw, are delay and future now basically the same, only that a future will run in its own thread?

7:36 (and also run immediately, while a delay will run lazily)

7:36 Chouser: I think that's right. Not a trivial difference.

7:36 AWizzArd: ok

7:38 Lau_of_DK: Thanks Chouser :)

7:39 I've updated the project Wiki, so you guys can see when it gets interestined (ie. not yet) http://wiki.github.com/Lau-of-DK/sofiaba

7:39 ...with screenshots

7:39 Chouser: cool

8:28 wlr: AWizzArd: recently you were interested in bit-twiddling. i stumbled upon http://java.sys-con.com/node/847250 haven't read it myself yet, though.

8:40 Vargr_: (possibly) stupid question: When I start clojure in an *inferior-lisp* with slime, I should be able to attach to that port with JSwat, no?

8:45 kotarak: Vargr_: I figure, it depends on how you start the java instance.

9:14 StartsWithK: what should i use if i want to walk, transform and exctract parts of the form?

9:15 so form could contain list, vector and map literals

9:15 is there anything i can use for that right now?

9:17 Vargr_: kotarak: why, do I need to observe something special here?

9:19 kotarak: Vargr_: I'm not very familiar with Java (coming from Scheme), but there is a debug option, when starting java, which (as I understand) allows you to connect a debugger. So I'm not sure, that you can connect the debugger, when you don't give the necessary options, when starting the java instance.

9:20 Vargr_: kotarak: oups, seems I've been trying to connect to swank then :)

9:21 * kotarak uses Vim.

9:22 kotarak: Vargr_: so I don't know anything about SLIME and swank. :)

9:23 Lau_of_DK: Ola mon kotarak ! :)

9:23 kotarak: StartsWithK: there is walk in clojure.contrib by Stuart Sierra.

9:23 Hi Lau_of_DK

9:23 Vargr_: thanks for the help anyway, kotarak

9:23 Lau_of_DK: Kota, you'll enjoy this in a few years :) http://wiki.github.com/Lau-of-DK/sofiaba

9:24 StartsWithK: Let me sketch, http://paste.pocoo.org/show/104912/

9:24 kotarak: i looked at it, but can't find any way to extract something, just transform in place

9:25 and when i find :id id1 pattern, i want to go back to (mymacro expr) and replace it with (mymacro id1), where :id id1 could be anywhere in body of mymacro

9:28 kotarak: Lau_of_DK: ui. Are you working on this?

9:29 Lau_of_DK: ui?

9:29 StartsWithK: Lau_of_DK: you switched from jogl to jme? hows that working?

9:30 kotarak: Lau_of_DK: "ui" a sound like "ah" or "oh"

9:30 Lau_of_DK: ah

9:30 StartsWithK: They're worlds apart - Not going back to jogl :)

9:30 kotarak: Yea - Sofia had a kick out of just switching screensavers on my laptop - So I thought I'd make a fun 3d game for her, figured the rest of you might like the 3D bindings

9:31 StartsWithK: Lau_of_DK: heh, just couple of day ago i started to do experiments with it too :) small world

9:31 kotarak: hehe :)

9:31 Lau_of_DK: Its a classic: Slam the keyboard = Fun effects and responses in the environment, type game

9:32 StartsWithK: had some problems placing jmecanvas and displaying swing menus around it

9:32 Lau_of_DK: Which superclass did you go with ?

9:32 StartsWithK: SimpleCanvasImpl

9:33 Lau_of_DK: Oh ok - Never heard of it

9:33 StartsWithK: with JOGLAWTCanvasConstructor

9:33 Lau_of_DK: I went with BaseGame, good for fullscreen 3D games - Sounded like something Sofia would enjoy :)

9:34 So far, Ive got the world drawn up, and you can fly around in it, thats it

9:34 StartsWithK: i needed more 'application' look, with swing components around canvas

9:34 Lau_of_DK: Also made some functions for loading resources quite easily

9:34 StartsWithK: resize still dosn't work :)

9:34 Lau_of_DK: Anyway, gotta run - Will probably be back tonight

9:35 StartsWithK: so.. any ideas how i could transform firs form in the one inside (let ..)

9:35 is there something like, xslt for clojure form :)

10:33 digash`: anybody going to ILC2009?

11:21 Chouser: digash`: yep

11:34 MarkVolkmann: I'm trying to understand the claim that using alter to change a Ref is more efficient than dereferencing, computing a new value, and using ref-set.

11:35 It seems to me this isn't a matter of efficient, just ease of coding.

11:35 If two threads are simultaneously trying to change the same ref in different transactions, with either approach, one of them is going to retry their transaction.

11:36 Am I missing something?

11:39 rhickey: MarkVolkmann: who made that claim?

11:40 MarkVolkmann: It's in Stuart's book ... page 180 of the latest PDF.

11:41 Is there a benefit to using alter instead of directly coding the three steps it comprises other than making the code simpler ... which is a good enough reason on its own.

11:43 rhickey: I don't see "more efficient" there, but "less contentious" is also not correct

11:44 MarkVolkmann: alter is by far preferred

11:49 MarkVolkmann: The line I'm looking at on page 180 of beta 7 says "The naive approach works, but it is inefficient."

11:49 Lau_of_DK: rhickey: Have you considered updating the gen-class documentation on clojure.org? I'll start pulling out my hair soon if you dont :)

11:50 MarkVolkmann: The three-step naive approach appears just above that sentence.

11:51 rhickey: MarkVolkmann: ah, please report to Stu

11:51 MarkVolkmann: Okay, I will. Thanks!

11:52 rhickey: Lau_of_DK: (doc gen-class) for now

11:53 * Lau_of_DK proceeds with hair-pulling

11:53 Lau_of_DK: oh wait no - there's good stuff in that doc actually

11:53 I'll read it - I thought it would be a slimmed down version of whats on the site :)

12:15 digash`: Chouser: where do i report bugs for contrib packages.

12:15 ?

12:16 Chouser: digash`: the regular Clojure google group.

12:16 digash`: Chouser: ok, thanks, I will send it there.

12:37 Chouser: ,(import '(java.util GregorianCalendar Calendar))

12:37 clojurebot: nil

12:37 Chouser: ,(.compareTo (GregorianCalendar.) (.add (GregorianCalendar.) Calendar/DAY_OF_MONTH 5))

12:37 clojurebot: java.lang.NullPointerException

12:37 Chouser: what am I doing wrong here?

12:37 (.compareTo (GregorianCalendar.) (.roll (GregorianCalendar.) Calendar/DAY_OF_MONTH 5))

12:37 ,(.compareTo (GregorianCalendar.) (.roll (GregorianCalendar.) Calendar/DAY_OF_MONTH 5))

12:37 clojurebot: java.lang.NullPointerException

12:44 AWizzArd: ,(conj #{5} #{1 2 3})

12:44 clojurebot: #{5 #{1 2 3}}

12:44 AWizzArd: ,(conj #{1 2 3} #{5})

12:44 clojurebot: #{1 2 3 #{5}}

12:44 AWizzArd: ,(conj 5 #{1 2 3})

12:44 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IPersistentCollection

12:44 AWizzArd: hmm

12:45 Chouser: add() desn't return the calendar. *sigh*

12:45 ,(conj #{1 2 3} 5)

12:45 clojurebot: #{1 2 3 5}

12:45 AWizzArd: Chouser: yeah, that i sone of the not so beautiful things of the JVM. Some methods just return nil

12:45 Chouser: ,(.before (GregorianCalendar.) (doto (GregorianCalendar.) (.add Calendar/DAY_OF_MONTH 5)))

12:45 clojurebot: true

12:47 Chouser: unfortunately, in this case it's probably the right thing to do, short of making the objects immutable.

12:47 sure helps you remember you're mutating a thing, not getting a new object.

12:49 AWizzArd: yes

12:51 MarkVolkmann: A question about transaction retries ...

12:51 I understand a transaction will retry if it attempts to modify a Ref that was modified by another thread since the current transaction began.

12:52 Does the retry automatically wait until that other transaction completes before trying again?

12:53 kotarak: MarkVolkmann: I think, the transaction sees the modified value only after the other transaction completed.

12:54 MarkVolkmann: Right, it doesn't see the other value, but it does not that another transaction changed it and that's why it retries.

12:54 My question is whether the retry begins as soon as it sees that situation or does it wait until that other transaction either commits or rolls back.

12:55 kotarak: MarkVolkmann: I don't think so. My understanding is, that the first transaction completes, and the another thread (which changed the ref) retries.

12:55 MarkVolkmann: Based on some test code I wrote it seems that it waits for the other transaction to finish. I just want to confirm that.

12:55 digash: Chouser: sorry about the noise about the bug, just did not fully sync up lazy branch with contribs.

12:56 Chouser: digash: ok, glad it's resolved.

12:56 MarkVolkmann: I think if two transactions try to change the same Ref, the first one that does it gets to finish and the other one retries ... but not until the first one finishes. I'd like to have someone confirm this though.

12:58 Chouser: I'm still too unskilled at reading the code in LockingTransaction.java

12:59 kotarak: MarkVolkmann: ok. I'm not that deep in the STM, but I got the impression, that the transactions are independent in the sense, that there is no "the first one gets it". Each transaction sees its value. And although the value might be changed in the transaction, if the other one commits first, this one has to try again. No matter which "first" changed the Ref.

13:06 AWizzArd: btw, why is there now a clojure-sources.jar? Is that for my classpath, so that debuggers like jswat can access all Clojure code?

13:08 MarkVolkmann: Okay, I just verified that my guess was wrong.

13:08 When a transaction restarts, it does not wait until other transactions whose changes made it restart complete.

13:09 It tries to make it's changes again, restarts again, over and over until it succeeds.

13:09 It's seems like not doing this may be a nice optimization ... unless I'm missing an important detail.

13:10 AWizzArd: kotarak: about your assumption "I think, the transaction sees the modified value only after the other transaction completed". rhickey told me some time ago that Clojure is semi-optimistic, and not fully. So it will not wait until the end of the transaction, but look from time to time if it makes sense to continue the transaction.

13:12 MarkVolkmann: I would say that a transaction does *not* wait for others to finish.

13:12 MarkVolkmann: Yeah, that's what I see in the results of my sample code.

13:12 AWizzArd: They all try concurrently to change the object, semi-optimistically.

13:12 oh ok

13:12 kotarak: AWizzArd: ok. As I said: in only got "impressions" and don't know the nitty-gritty

13:12 AWizzArd: kotarak: yes

13:13 MarkVolkmann: This really illustrates the difference between using alter and commute.

13:13 AWizzArd: how?

13:14 MarkVolkmann: commute just keeps going through the transaction, modifying the in-transaction values even though another transaction has changed them. Then at the end of the transaction it reapplies the update functions using the last committed values.

13:15 In the output of my sample code, I can see lots of retries when I used alter, but not when I use commute.

13:16 AWizzArd: so commute will not retry as often?

13:17 slashus2: Order doesn't matter.

13:18 MarkVolkmann: It seem to me commute will never retry. It will just use in-transaction values. The key point is that at the end of the transaction after it has decided to commit, it will call all the update functions again to ensure that their updates are based on the latest committed values, not in-transaction values.

13:19 Someone please correct me if I've saying something wrong!

13:19 slashus2: The order that you call the commutes in the transaction doesn't matter?

13:20 MarkVolkmann: I don't know about that. I think it does. My point is that what is happening in other transactions that modify the same Refs doesn't seem to matter until the commit point.

13:21 That's when it calls all the update functions a second time.

13:21 ... using last committed values instead of in-transaction values.

13:25 Chouser: right, commutes never cause a retry.

13:26 the function given to a commute is always called twice -- once to get the in-transaction value, once to get the commit value.

13:29 AWizzArd: hmm

13:30 but couldn't it be possible that some changes were made that make the commute superfluous?

13:31 If it does not rerun the transaction, it can not find out if this is the case

13:33 Maybe commute is simply the wrong thing for transactions like that

13:34 for example for transferring money from one account to another (money in an online game, whatever). If one account is empty then no transfer should happen. But the if that checks for the balance is on top of the transaction.

13:35 MarkVolkmann: anyway, good point, thanks for your test

13:36 MarkVolkmann: Sure!

13:37 AWizzArd: MarkVolkmann: have a look into your private messages

13:46 Lau_of_DK: Good evening gents

13:50 danlarkin: hey what's a quick way to get an NPE? I'm testing my exception reporting

13:50 Chouser: ,(nil)

13:50 clojurebot: java.lang.IllegalArgumentException: Can't call nil

13:50 Chouser: oh

13:50 rhickey: (.foo nil)

13:51 danlarkin: gracias

14:46 leafw: the webpage needs updating: clojure.org/lazy says "(Note: this section describes work in progress, currently only available in the lazy branch of SVN)"

14:47 cgray: hi, is there a modulo function that's convenient to use?

14:47 redalastor: cgray: rem

14:48 gnuvince_: ,(rem 5 2)

14:48 clojurebot: 1

14:48 rhickey: leafw: updated, thanks

14:48 cgray: redalastor: thanks

14:48 leafw: you're welcome.

14:48 Chouser: ,(mod 5 2)

14:48 clojurebot: 1

14:49 cgray: i tried mod...

14:49 Chouser: cgray: it's more recently added than rem

14:49 cgray: i wonder why it didn't work for me

14:51 leafw: does doseq hold onto the head of a sequence?

14:51 Chouser: it shouldn't

14:51 leafw: ok.

14:53 so (doseq [i coll] ...) is the same as (loop [c coll] (if coll (do ..<use (first coll)>. (recur (rest coll)))))

14:55 Chouser: next not rest. you could macroexpand.

14:57 leafw: sorry, still on pre-lazy merge.

14:58 Chouser: ah. well, macroexpand should still work. :-)

15:00 leafw: Chouser: it does, but it shows ... lots of gutter

15:00 ,(macroexpand-1 '(doseq [i (range 5)] (println i)))

15:00 clojurebot: (clojure.core/loop [sq__3897__auto__ (clojure.core/seq (range 5))] (clojure.core/when sq__3897__auto__ (clojure.core/let [i (clojure.core/first sq__3897__auto__)] (clojure.core/when true (clojure.core/when true (do (println i))) (recur (clojure.core/next sq__3897__auto__))))))

15:00 leafw: notice the double when true when true.

15:00 is that really needed?

15:01 i.e. I don't understand why it's there.

15:02 Chouser: leafw: that's just to make the macro itself simpler. hotspot should get rid of the extra work in short order.

15:02 leafw: what does "in short order" mean?

15:03 I am sure the doseq macro handles much more cases than the simple one above.

15:05 danlarkin: Hm. this is throwing the LazySeq used in 'if' exception: (if-let [result (context (keyword k))] ...)

15:05 Chouser: leafw: I mean that it is easy for hotspot to optimize away constant tests like that, so very few iterations should be necessary for it to catch on.

15:06 danlarkin: context is a hash-map and k is a string

15:06 Chouser: leafw: yes, those extra tests are for supporting the :when and :while options.

15:06 leafw: thanks.

15:07 Chouser: danlarkin: and the value is a lazy seq? :-)

15:09 danlarkin: Chouser: Hm, yup that's the problem

15:10 I can't run (seq ...) on it though, since it isn't necessarily a sequential structure

15:11 Chouser: sometimes it's a lazy-seq and sometimes it's something else?

15:11 danlarkin: correct

15:12 rhickey: then how is the if-let correct?

15:13 danlarkin: not sure what you mean? I suppose it isn't correct, since it can end up testing for truth on a lazy seq

15:15 rhickey: danlarkin: if it's a "I have something or not (nil)" scenario then this is a false positive, since even an empty lazy seq is something

15:15 you don't need to fix it, but it won't work with the flag on

15:17 Chouser: pre-lazier it might have been correct, I suppose -- true if a non-empty seq or something else

15:17 danlarkin: lisppaste8: url

15:17 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

15:17 rhickey: I think it's still correct, not all tests of lazy seqs are wrong

15:18 Lau_of_DK: rhickey: What criteria do you use to pick between proxy and gen-class?

15:19 rhickey: The whole point of () != false is to distinguish an empty thing from nothing, so a something/nothing detector is valid for lazy-seqs - not nothing

15:19 lisppaste8: danlarkin pasted "if-let" at http://paste.lisp.org/display/75976

15:20 Chouser: yes, the assert can definitely fire in cases that are actually correct.

15:20 danlarkin: so with assert-if-lazy-seq on that throws the warning, but is it actually correct?

15:20 rhickey: danlarkin: right, you want to see if there's something at key :foo

15:22 danlarkin: okay then, good to know

15:22 rhickey: it's not code that tested for empty with sequence return directly, the wrongness comes from your intent with if - is it if-there-is-a-colelction or if-non-empty-collection?

15:24 danlarkin: well the value for the key can be anything, including a lazy seq

15:24 Chouser: (map #(if % :a :b) [1 (map identity [2]) (map identity [])])

15:25 that used to return [:a :a :b], and would now return [:a :a :a]

15:25 I think.

15:26 rhickey: right, if you want emptiness test you need seq

15:26 Chouser: that's pretty contrived, but to get the old behavior now would take a few more words

15:29 #(if (if (coll? %) (seq %) %) :a :b)

15:30 rhickey: Chouser: if that's really the intent they should seq the map results

15:32 lisppaste8: danlarkin annotated #75976 "untitled" at http://paste.lisp.org/display/75976#1

15:32 Chouser: ah, good point.

15:32 danlarkin: okay, I can rewrite it that way and avoid this issue

15:32 xoox: Is there a predicate that always returns true?

15:32 Chouser: (constantly true)

15:32 xoox: thanks

15:34 Chouser: what are the possible value types of 'context'?

15:34 really anything?

15:34 danlarkin: it's user supplied, so anything

15:35 this is library code

15:35 Chouser: and you need to accept lazy seqs and force them yourself to find out if they're empty, rather than requiring the user to force them?

15:35 and yet treat other empty collections as true?

15:37 danlarkin: heh, all this code needs to do is first check if (keyword k) is in the map and if it is, return that -- otherwise return (context k)

15:39 Chouser: (contains? context k)

15:39 Lau_of_DK: Guys - Which criteria do you use to pick between proxy and gen-class? It seems to me theres a big overlap of functionality

15:40 rhickey: Lau_of_DK: proxy

15:40 Chouser: Lau_of_DK: I use proxy whenever I can, as I'm sure you've gathered.

15:41 danlarkin: Chouser: oh yes, contains? is (basically) what I used in my annotation. I used some... didn't realize contains? was in core now

15:41 Lau_of_DK: rich normally Im impressed by how concise you can be - but this time you took it too far :)

15:41 Chouser: And I want to follow that example, but I dont want to write a full proxy extension of a class to find out I should have gone with gen-class, so I need more info :)

15:41 rhickey: Lau_of_DK: if proxy meets the need, use it

15:42 Chouser: Lau_of_DK: gen-class only if I absolutely need to add a method, get a specifically-named class, or access protected members of the superclass.

15:42 Lau_of_DK: Ok, so if you just need a class, built on a superclass, but which has custom fields and methods, you'd go with proxy ?

15:43 Chouser: I've been intending to poke around inside proxy and see if it's really impossible to have it allow access to protected members.

15:43 Lau_of_DK: proxy can't add members beyond what the superclasses or interfaced define.

15:44 Lau_of_DK: Chouser: I just realized that my question was partly spawned from a naive intention of just directly porting java code, when Clojure actually provides a better alternative

15:45 Chouser: yeah, that's common when dealing with both proxy and gen-class.

15:45 Lau_of_DK: :)

15:45 Chouser: i've got a blog entry percolating about some techniques for moving Java idioms to clojure ones.

15:45 Lau_of_DK: This is where binding JMonkeyEngine will be interesting though - to see how much of it I can wrap in Clojurecode

15:45 Chouser: especially as found in Java library examples

15:45 Lau_of_DK: Cool - I really need to hook up some RSS to your blog

15:47 Chouser: "percolating" is code for "I'll probably never get around to it"

15:48 Lau_of_DK: oh...

15:48 Chouser: I've had a blog entry comparing iterator constructs in several languages for a few years now

15:48 Lau_of_DK: *cough* *geek* *cough*

15:48 Try reading that sentense out loud Chris :)

15:49 Chouser: percolating

15:49 that word belongs in there somewhere.

15:49 gnuvince_: Does anyone know of a blog post/article that would help people understand closures if they've never used them before?

15:55 ayrnieu: I'd go with http://letoverlambda.com/index.cl/guest/chap2.html

15:56 digash: what is the best way to store jvm/global state?

15:57 like i have an external sensors which I cannot access more often than ten times per second

15:57 so where do i store last-access-time?

15:58 ayrnieu: throttle the access through an agent.

15:59 digash: interesting, is there some example somewhere? i am not familiar with agents.

15:59 Bracki: cooldude127: Thx for your improved find-path function.

16:01 I must admit though, that the (or (and (not (includes?.. part is hard to graps.

16:01 grasp

16:01 * Bracki is talking about http://paste.lisp.org/display/75813#4

16:02 * digash is reading agents page at clojure.org

16:03 Bracki: ,(doc declare)

16:03 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

16:03 ayrnieu: digash - not of this; but after you become familiar with agents, it'll be very easy.

16:05 digash: ayrnieu: I dont get it yet, how to use agents to do throttle

16:07 ayrnieu: digash - you have the agent access the external device. It can sleep for a calculated (based on a last-access in its own state) or for a set time, and then access the device. Every request that the agent access the device will be interleaved and, with the agent sleeping, throttled.

16:07 but actually, I'm thinking like an Erlang programmer. Just use a clojure.

16:08 digash: ayrnieu: i see, use agent like erlang process and send requests to it.

16:09 hiredman: or you could create your own thread pool executor

16:09 that executes requests no faster then ten per second

16:11 Chouser: I think ayrnieu's first suggestion sounds good -- and agent that sends to itself to refresh its own state based on the sensor

16:11 ayrnieu: digash - the agent would throttle access even from multiple concurrent askers. If you don't have this, a closure is sufficient.

16:12 Chouser: then all the other code can read the agent value whenever necessary.

16:12 Bracki: Puh, the agent example code is awfully hard to understand.

16:12 ayrnieu: yeah, that's an excellent suggestion.

16:12 much better than mine :-)

16:27 senxhnsshp: how do I chekc if something is null? nil?

16:27 ie a java object

16:27 Chouser: yes, or just use in a boolean context

16:28 ,(if (new Object) :true :false)

16:28 clojurebot: :true

16:28 Chouser: ,(if nil :true :false)

16:28 clojurebot: :false

16:36 digash: ayrnieu: yes, i need to throttle from multiple askers, so that is why clojure is not enough for me.

16:36 closure^

16:38 thanks for the suggestions i will try out the agent, how big is the send queue?

16:41 Bracki: How do I make a :key from a "string"?

16:41 hiredman: ,(keyword "string")

16:41 clojurebot: :string

16:44 ayrnieu: digash - use Chouser's suggestion.

16:44 digash - if it's acceptable to access the external device every 1/10s

16:53 Lau_of_DK: Re gen-class, my :init function, can it accept clojure-types, and when Im told to return 'state', what is meant ?

16:55 hiredman: well, generally, a constructor sets up an initial state for a class

16:56 er

16:56 object

16:56 AWizzArd: hiredman: can one also have uninitialized objects in Java?

16:56 Lau_of_DK: hiredman: yea...so... whats state?

16:57 hiredman: some kind of state

16:57 Chouser: gen-class classes get a single immutable state field

16:57 hiredman: I think I returned a ref

16:57 for state

16:58 Chouser: as named by the :state option

16:58 hiredman: and the ref got put in the state field

16:58 Lau_of_DK: Ah - So why isnt that just returned automatically ?

16:58 Why do I have to do :state name, and then later return name

16:59 hiredman: no

16:59 you don't return the name

16:59 you return the value to be put in the field

16:59 Lau_of_DK: quote rich: Must return [ [superclass-constructor-args] state]

16:59 If not supplied, the constructor args are passed directly to

16:59 the superclass constructor and the state will be nil

17:00 hiredman: the state field's value will be set to nil

17:01 senxhnsshp: is it normal for just simple GUIs to take sveral hundred lines of code? i made na mp3player using JLayers decoder so I did just the GUI myself(in swing). it has play, stop, shuffle, and some playlist-functions. it is about 400 lines of code...seems a lot althought everything seems necessary

17:01 wait around 300 LOC in clojure

17:01 AWizzArd: senxhnsshp: did you write those lines manually?

17:01 senxhnsshp: now a lot of it is just wrapping java so it doesnt mean 1000 loc java but still

17:01 yes manually, how else?

17:02 AWizzArd: I did that.

17:02 Once.

17:02 Thank you, but, no thanks :)

17:02 I am now using NetBeans

17:02 You can download it for free and click your gui together.

17:02 senxhnsshp: ok, and it has a GUI for making GUIs?

17:02 Lau_of_DK: senxhnsshp: Checkout MigLayout

17:02 senxhnsshp: oh nice, lol

17:02 AWizzArd: senxhnsshp: it has maybe the best gui builder available

17:02 definitly one of the best

17:03 senxhnsshp: im using miglayout

17:07 lisppaste8: bracki pasted "What's wrong with the join function?" at http://paste.lisp.org/display/75986

17:07 Bracki: First branch of the if statement doesn't work.

17:09 hiredman: Bracki: paste the exception too

17:09 or explain what you mean by "doesn't work"

17:09 lisppaste8: bracki annotated #75986 "untitled" at http://paste.lisp.org/display/75986#1

17:10 hiredman: actually

17:10 cons needs to be conj

17:10 Bracki: Why?

17:10 Chouser: the first arg of commute needs to be a ref, not a vector

17:11 hiredman: cons takes arguments in a different order then conj

17:11 ah

17:11 indeed

17:11 pilkarn: doesnt eclispe have somthing similar? i tried netbeans once and hated it. so slow and big

17:12 Bracki: Hm, but isn't that a ref?

17:12 Chouser: *channels* is a ref

17:12 hiredman: @*channels* is whatever the ref points to

17:12 Bracki: So I put all the dereferencing after that?

17:13 Chouser: yes

17:13 hiredman: er

17:13 no

17:13 Chouser: you might like update-in for that

17:13 hiredman: commute does the deref for you, doesn't it?

17:14 Bracki: But why does this: http://github.com/technomancy/mire/blob/e6c8943d9dd717fdb44654f248a03dcf1d2915d0/src/mire.clj#L18-23 work?

17:14 slashus2: AWizzArd: So you create the GUI part with netbeans, and the rest with clojure?

17:14 Chouser: true, I was thinking he meant the key lookup

17:14 hiredman: ,(commute (ref 1) doto prn)

17:14 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/doto

17:14 hiredman: bah

17:15 Bracki: Ah because bloody :inhabitants is a ref as well.

17:15 technomancy: Bracki: which line in particular? there are nested refs

17:16 Bracki: if you're going to read the mire source, I'd recommend reading one branch at a time.

17:16 the application is written step-by-step where each step builds on the last

17:16 Chouser: Bracki: (commute *channels* update-in [(keyword channel)] conj user)

17:16 technomancy: and each step is separated into its own branch.

17:16 I really need to update the readme to explain that.

17:17 Bracki: I hadn't looked at rooms.clj, I just assumed it to be a vector and not a ref to a vector.

17:18 hiredman: ,(pl inc $ inc $ inc $ 0)

17:18 clojurebot: 3

17:21 pilkarn: isnt it possibel to use skins for swing guis?

17:33 AWizzArd: senxhnsshp: watch 6 minutes: http://www.netbeans.org/kb/60/java/swing-app-beans-binding-screencast.html

17:33 you get an impression of what NetBeans can do for your gui

17:34 (you want to watch it maximized)

17:34 slashus2: yes, I click my guis together with NetBeans and write the rest in Clojure

17:35 for example the event handlers

17:38 slashus2: How do you set up the event handlers to use clojure code? Just call clojure methods?

17:40 AWizzArd:

17:40 * technomancy discovers slime-macroexpand-1... whoa.

17:41 AWizzArd: slashus2: with a proxy

17:44 In NetBeans I write an export method which returns all objects which I want to touch in Clojure. It's very simple, just a few lines, no thinking needed.

17:45 In Clojure then I make an instance of the class that NetBeans automatically generated, and call (.export my-frame), to get an array of all the widgets.

17:46 Chouser: AWizzArd: it generates Java source code for you, that you then compile?

17:46 scode: I want to implement a blocking "wait for something to complete" (in this case, wait for some backgroudn I/O to complete). Would it be ideomatic to send-off a blocking function which does a mutex wait, and await? This is assuming there is hidden mutable state that is being waited on.

17:47 Chouser: scode: have you looked at 'future'?

17:48 scode: Chouser: No, not in clojure. Contrib lib?

17:48 CardinalFang: Hi all. I'm trying to piece together a Ant "makefile" to create ahread-of-time compiled class files, which can package and do Stuff with. I'm having trouble with how to do that. I want to use some command-line doo-dad like "javac", which will take .clj and emit .class.

17:48 Chouser: scode: nope, recent addition to core

17:48 (doc future)

17:48 clojurebot: Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block.; arglists ([& body])

17:48 scode: Chouser: Futures would be nice, even if somewhat implicit in this case.

17:48 Chouser: Ah cool. Thanks!

17:49 CardinalFang: ...but my thinking may not be at all Lisp-y. Please correct me or suggest something.

17:49 hiredman: CardinalFang: the clojure source tree has a build.xml in it that does AOT compilation, so you should look at that

17:49 CardinalFang: Ooo.

17:50 "clojure.lang.Compile". Perfect. Thanks for the tip, hiredman.

17:54 scode: Chouser: Btw, any place to figure out that futures got added, other than following svn more closely? Did not see obvious mention on the ML (subject search ;)).

17:55 Bracki: technomancy: If I understand everything correctly, the binding part in mire-handle-client makes the whole thing work right?

17:56 AWizzArd: Chouser: yes, I compile the code in NetBeans. The .class files it generates I then put into my classpath that I set up in emacs. Then I can simply import these NetBeans classes in Clojure. I simple (import ..) will do.

17:57 technomancy: Bracki: the binding part is one of many parts that makes the whole thing work. =)

17:57 Bracki: could you be more specific?

17:58 Bracki: Well, I wondered how you associate a user's state with *name*.

17:58 technomancy: Bracki: ah yes, everything that needs to be thread-local happens in binding.

17:59 Bracki: I had expected that you have to save the connection info for every user somewhere, but this way you don't.

17:59 Lau_of_DK: technomancy: Is SLIME/Swank-clojure up and running with the latest rev. of Clojure?

18:00 technomancy: Lau_of_DK: looks like it.

18:00 Lau_of_DK: cool

18:00 technomancy: Bracki: sure, you "save" it in a binding. but you don't alter anything that already exists.

18:01 Bracki: the one exception is that you add each player's *out* stream to the *players* map so that players can speak to each other.

18:04 Bracki: technomancy: Can players change their nicks?

18:05 technomancy: Bracki: nope, not without reconnecting

18:05 does slime's fuzzy-completion package work with swank-clojure?

18:08 ayrnieu: for another way of doing this, look at chat-serve.clj and its used libraries in http://github.com/ayrnieu/clj-actors/

18:14 Bracki: No, that'll spoil the fun and make my humble attempts seem useless.

18:14 But I'll look anyways.

18:18 good night.

18:43 MarkVolkmann: I've got a question about root bindings of Vars.

18:43 (def my-var 1) ; gives it a root binding of 1

18:43 Isn't the only way to give it a new root binding, to all def again like this?

18:43 (def my-var 2)

18:44 Chouser: or alter-var-root

18:44 MarkVolkmann: I'm experimenting with watchers.

18:44 They aren't catching that change to the Var.

18:44 Chouser: they will if you use alter-var-root

18:45 MarkVolkmann: But not if I use def?

18:45 Chouser: I think that's correct.

18:45 MarkVolkmann: Thanks! I'll try it.

18:49 If I add a watcher to a Ref and then change the Ref with ref-set two times in a transaction, should the watcher be notified once or twice?

18:49 Maybe just once since the first change is only to the in-transaction value.

18:49 Does that sound right?

18:50 ayrnieu: Mark - the watcher won't be notified until the end of the transaction, as with all sends to agents.

18:54 Chouser: there are changes planned for the watcher api

18:55 http://code.google.com/p/clojure/issues/detail?id=80

18:56 MarkVolkmann: Thanks!

18:56 The web page "Vars and the Global Environment" says this about def:

18:56 "Supplying an initial value binds the root (even if it was already bound)."

18:56 That sounds like it can be used to give a new root value to an existing Var.

18:57 How does it differ from alter-var-root other than than alter-var-root takes an update function?

18:58 Chousuke: maybe alter-var-root is atomic?

18:58 hmm

19:03 Chouser: looking at the code, it appears that both 'def' and 'alter-var-root' should do validation and notify watchers.

19:04 that seems to work.

19:05 MarkVolkmann: you might try your experiment again

19:07 lisppaste8: Chouser pasted "watchers on a Var" at http://paste.lisp.org/display/75994

19:12 MarkVolkmann: Thanks!

19:12 I think the issue is the way I'm tracking the changes.

19:13 My agent state is a map where the keys are reference objects and the values counts of the number of times that reference has changed.

19:13 For some reason this works for refs and atoms, but not vars.

19:13 I suspect there is a problem with the way I'm trying to use Var objects as keys.

19:13 Still digging ...

19:13 I sent my code to the mailing list.

19:17 I realize watchers won't get notified about calls to set!, but I'm trying to learn how to call set!.

19:17 It wants a var-symbol, not a var.

19:17 How do I get that?

19:18 Chouser: (def foo 7) (set! foo 42)

19:20 senxhnsshp: hmm does javax.media come with java? because i cant find the jar in clojure-java-jars but i can import it. wodnering if maybe i put it somehwere weird

19:20 MarkVolkmann: That's what I was trying initially. I'm getting IllegalStateException: Can't change/establish root binding of: my-var with set

19:21 I get the same thing when I run your code example in a REPL.

19:23 Chouser: MarkVolkmann: yes

19:23 that's correct

19:23 :-)

19:23 MarkVolkmann: Is it clear why that doesn't work?

19:23 Chouser: ,(binding [filter 99] (set! filter 7) (prn filter))

19:23 clojurebot: 7

19:23 senxhnsshp: how does stuff like RealPlayer and DivX make money?

19:24 Chouser: 'set!' is only allowed when a thread-local binding has been created

19:24 MarkVolkmann: Okay, thanks!

19:25 jochu: technomancy: swank-clojure doesn't support fuzzy completion as of yet. It does have compound prefix completion though.

19:26 AWizzArd: hmm, I didn't know about this alter-var-root. Is it new in Clojure? Why are so many side-effectish things added?

19:27 drewr: AWizzArd: I was just thinking that.

19:27 rhickey: AWizzArd: don't use them!

19:28 AWizzArd: I won't. But their existance will be heaven for people coming from imperative languages.

19:28 drewr: ...and their demise. Muahaha.

19:31 AWizzArd: I mostly considered def as a defconstant. That one can overwrite it with a new def was only for allowing dynamically evolving the system during runtime, and for administrative purposes.

19:34 Chouser: the naming convention for vars that will be changed with alter-var-root is like: ==>->foo<-<==

19:35 * clojurebot blinks

19:36 Chouser: consensus by fiat

19:36 AWizzArd: well, the name is of course a bit longer than setf, and it is not as easy to use, but basically it sounds as if Clojure has very easy access to imperative operators now.

19:38 Chouser: it always did, thought Java interop, re-def'ing, etc. We just politely remind people they shouldn't do it every time they ask a question.

19:38 eventually they stop asking

19:38 ayrnieu: and Erlang can get()/put() everything, and Haskell and use functionsWithScaryNames

19:39 Chouser: ,(let [x (clojure.lang.Box. 7)] (set! (.val x) 42) (.val x))

19:39 clojurebot: 42

19:39 AWizzArd: maybe these set!s and alter-var-root things should just disappear, to enforce a less imperative style

19:39 rhickey: yes, Clojure is not generally about prohibition, but rather recipes and ingredients for success

19:39 Chouser: ,(let [x (atom 7)] (swap! x inc) @x)

19:39 clojurebot: 8

19:40 AWizzArd: the atom approach is different

19:40 Chouser: is it really?

19:40 AWizzArd: it is one of the few explicit constructs for managing state

19:40 Chouser: I mean, it's slightly different, but pretty easy to abuse

19:40 AWizzArd: yes

19:41 Was nicer when there were only refs and agents

19:41 Chouser: nah

19:41 rhickey: AWizzArd: then just use refs and agents

19:41 ayrnieu: as if you can't abuse refs and agents.

19:41 rhickey: real programs need more, and I'm happy to oblige - I've done a lot of MT programming and I want to make it safe

19:42 Chouser: agents are pretty easy to abuse -- refs a bit harder.

19:42 AWizzArd: rhickey: well, I don't see the problems for myself or my team. We can have an agreement of not using set! or alter-var-root without having a meeting first.

19:42 * rhickey is working on a deadlock-free mutex reference type

19:42 rhickey: AWizzArd: exactly right

19:42 AWizzArd: ayrnieu: yes, one can abuse anything, it just was very obvious what those constructs are for

19:43 I am not so convinced that people coming from imperative langauges will also have so strict rules

19:44 rhickey: AWizzArd: all the mutable reference types have the same effect on a program's referential transparency, they only differ in concurrency semantics, all sharing safety

19:45 Chouser: rhickey: do you have any thoughts about printing type hints as propogated by the compiler?

19:45 AWizzArd: rhickey: yes, it's of course safer this way, but still.

19:45 rhickey: printing during compilation?

19:45 AWizzArd: hmm, good idea.. one could have a warning for each set! and each alter-var-root that can not be surpressed

19:45 that would be a nice thing

19:46 Chouser: rhickey: yeah, I guess. or with a separate step like macroexpand

19:46 rhickey: AWizzArd: sorry, responding to Chouser's q

19:46 Chouser: AWizzArd: cannot be supressed!? yikes

19:46 AWizzArd: :)

19:46 rhickey: Chouser: I think there is a general need amongst tools to access to the analysis tree

19:47 ayrnieu: AWizzArd, write a clojure lint. Popularize it. Recommend it to newbies. etc.

19:47 * rhickey needs to rewrite the compiler in Clojure

19:48 rhickey: in my spare time :)

19:48 Chouser: rhickey: that task doesn't really need you, does it? or do you have Grand Plans?

19:48 AWizzArd: ayrnieu: yes, I discussed this with a few people already. It could have an optional static type system. But maybe Mark Tarver can be convinced to port Qi to Clojure :)

19:48 te: Hello all.

19:49 AWizzArd: Hello te

19:49 Chouser: te: hi

19:49 rhickey: Chouser: I don't know, there's just the last little bit I had/have to do in Java I'd like to get rid of

19:49 te: How goes the clojure hacking?

19:50 rhickey: AWizzArd: I think once we have Datalog you will be able to build a logical model of type signatures and validate it, completely outside of the code

19:50 AWizzArd: sounds good

19:51 I had something like the Erlang Dialyzer in mind.

19:51 rhickey: I like Qi's approach

19:51 AWizzArd: yes

19:52 the Dialyzer is doing completely optional type analysis and referring to http://www.it.uu.se/research/group/hipe/dialyzer it found several bugs in a huge code base

19:52 "Dialyzer has been applied to large code bases, for example the entire code base of AXD301 consisting of about 2,000,000 lines of Erlang code, and has identified a significant number of software defects that have gone unnoticed after years of extensive testing."

19:53 obviously in a dynamic system not all potential type errors can be caught

19:53 powr-toc: I'm toying with some concurrency code which needs to read/write state to disk. Naturally I need to prevent parallel read/writes to the same data... I'm looking at implementing it with two agents (with watches) each managing a hashmap of executing reads/writes, so as to effectively perform a read/write lock... does this sound reasonable? Or should I just use a java concurrent read/write lock?

19:54 te: If I manage to hang the REPL in emacs-- is there is a command to abort running that code, or do I need a new REPL?

19:55 AWizzArd: powr-toc: maybe an agent that removes read/write jobs from a queue and runs them, while any number of other threads write their jobs into that ref?

19:56 rhickey: powr-toc: if the targets are known, you can just set up an agent as a gatekeeper for each one, an agent will effectively serialize access

19:57 powr-toc: AWizzArd: that would serialize reads though. I want to parallelise reads and only lock in the case where a read/write is done to the same location.

19:57 (I want to parallelise writes as well).

19:58 AWizzArd: Chouser: did you just say that the watcher interface will change?

19:58 Chouser: AWizzArd: http://code.google.com/p/clojure/issues/detail?id=80

19:59 AWizzArd: thx

20:00 btw, is force still needed?

20:00 It seems delays now work fine with deref

20:00 rhickey: AWizzArd: force allows apis that work on both delays and non

20:00 ,(force 42)

20:00 clojurebot: 42

20:01 AWizzArd: oh good

20:01 rhickey: ,(deref 42)

20:01 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IDeref

20:01 powr-toc: rhickey: That sounds like the approach I'm taking... I'm pretty new to clojure, so I'm just sanity checking. Essentially I'm wanting to implement a simple key/value database-store, to cache large pre-calculated datasets in a concurrent application

20:01 AWizzArd: apropos delays, does it make sense to run them in their own thread, just as futures, with the difference that their threads don't run immediately?

20:02 Chouser: AWizzArd: why?

20:02 AWizzArd: makes not much sense right?

20:03 the thread requesting data would have to wait anyway

20:03 Chouser: I'm just wondering what benefit you see in suggesting the change.

20:04 AWizzArd: maybe there is an obvious benefit that I haven't seen *shrugs*

20:05 pilkarn: can i call super from clojure?

20:05 Chouser: pilkarn: yes. proxy or gen-class?

20:07 AWizzArd: pilkarn: btw, a cool tool that Clojure offers is find-doc. It can help to find starting points if you have some term about the issue: (find-doc "super")

20:11 pilkarn: what license do I use for: here is what I wrote, do whatever you want with it and blame for anything and yes you can close the source(ie not gpl) fi you want but you cant add something to it and then claim i cant use that.

20:16 lisppaste8: pilkarn pasted "super java" at http://paste.lisp.org/display/75997

20:16 slashus2: ayrnieu: http://github.com/ayrnieu/clj-actors/ <-- Is this an example of how the actors model may look in clojure if it is ever added?

20:16 pilkarn: ^^

20:19 ayrnieu: slashus - no, it's an actors library with a networking library, and some examples.

20:20 AWizzArd: ,(find-doc "weak")

20:20 clojurebot: nil

20:21 pilkarn: how would I implemetn my paste? with gen-class or proxy?

20:21 powr-toc: what would be idiomatic clojure for writing a serializable object to disk?

20:21 ayrnieu: the 'Concurrent architecture for Clojure' tagline says enough. If you're interested in it, you should fork it. Add a distribution layer, etc.

20:21 powr-toc: is it to drop to java?

20:22 Chouser: powr-toc: For clojure objects you can use prn and friends.

20:22 AWizzArd: powr-toc: you can (binding [*print-dup* true] (print my-clojure-object))

20:23 Chouser: pilkarn: probably proxy

20:23 AWizzArd: in in that binding you can as well bind *out* to some stream that points to your file

20:24 powr-toc: Chouser: does that serialize as an ascii sexp, or as a binary sexp, or something else?

20:24 Chouser: powr-toc: ascii sexp. well, utf-8 probably

20:24 AWizzArd: ,(binding [*print-dup* true] (print [1 2 3]))

20:24 clojurebot: [1 2 3]

20:24 AWizzArd: ,(binding [*print-dup* true] (pr-str [1 2 3]))

20:24 clojurebot: "[1 2 3]"

20:25 AWizzArd: ,(binding [*print-dup* true] (pr-str {:a 1 :b 2}))

20:25 clojurebot: "#=(clojure.lang.PersistentArrayMap/create {:a 1, :b 2})"

20:25 powr-toc: I guess that'll do for now... Whilst I get the concurrency stuff sorted out... Ultimately though I'll need to serialize large bitsets

20:27 cp2: i love github

20:28 powr-toc: What is the convention around *foo* variables? And where are they documented?

20:28 cp2: useful to look at everyone's clojure projects

20:28 :)

20:29 durka42: powr-toc: all the *foo* vars are supposed to have docstrings

20:29 ,(doc *print-dup*)

20:29 clojurebot: "; When set to logical true, objects will be printed in a way that preserves their type when read in later. Defaults to false."

20:29 Chouser: powr-toc: indicates the var is meant to be rebound using 'binding'. Dunno if it's documented anywhere other than in lengthy discussion group threads.

20:30 durka42: lots of vars without * have doc strings.

20:30 powr-toc: durka42: Ok, I tried that and got back nil for print-dup... I guess my clojure's a little long in the tooth :-)

20:30 durka42: well, since fns are vars, i suppose so :)

20:31 powr-toc: ok, I'm on svn rev 1162... guess I need an update :-)

20:31 hiredman: ~latest

20:31 clojurebot: latest is 1299

20:31 ayrnieu: you can say it's a CL-ism that doesn't make sense when you separate binding from let , or you can say that it helps identify a global environment variable like print-dup without , in a lisp-1 , interfering with the function itself.

20:31 durka42: be careful updating... you may break everything

20:32 isn't 1162 the last revision before the move to google code?

20:32 ~svn rev 1163

20:32 clojurebot: svn is http://clojure.googlecode.com/svn/trunk/

20:32 hiredman: svn rev 1163

20:32 powr-toc: durak42: probably is... svn up doesn't update... I'll switch repos and try again

20:33 hiredman: clojurebot's svn.clj needs an over haul

20:33 te: I am struggling a little bit to understand refs and dosync

20:33 powr-toc: are there any plans to migrate clojure to git, or is that a dirty word? :-)

20:34 ayrnieu: te - http://en.wikipedia.org/wiki/Software_transactional_memory

20:34 powr - look for clones on github.

20:34 te: ayrnieu: thanks ill read it

20:34 AWizzArd: powr-toc: there already is a clojure repo

20:34 but svn works very well for rhickey so far

20:34 clojurebot: svn rev 1163; made default build run clean

20:35 powr-toc: Is it frequently updated?

20:35 te: ayrnieu: what about persistence with the STM?

20:35 AWizzArd: btw, why git and not Mercurial? ;)

20:35 powr-toc: yes, very frequently

20:35 ayrnieu: te - what about it?

20:35 te: ayrnieu: Just trying to understand if persistence applies to the STM or not

20:35 powr-toc: AWizzArd: is it a direct clone, or are there other patches applied to it?

20:35 AWizzArd: direct clone

20:35 ayrnieu: te - they have nothing to do with each other.

20:36 te: ayrnieu: thanks

20:36 powr-toc: AWizzArd: is this the repo? git://github.com/kevinoneill/clojure.git

20:36 AWizzArd: exactly

20:36 powr-toc: sweet

20:36 slashus2: What about bzr?

20:37 AWizzArd: a few months now it gets very frequent updates

20:37 slashus2: bazaar VCS

20:37 powr-toc: lol - I didn't mean to start a flame war... I should never have asked :-)

20:37 AWizzArd: maybe darcs?

20:38 pilkarn: clojure uses STM right?

20:38 durka42: yes, with refs

20:38 ayrnieu: pilkarn - refs provide STM.

20:38 slashus2: Bazaar is similar to git, but it doesn't have as steep of learning curve.

20:38 AWizzArd: yes

20:38 pilkarn: we should make a distributed version ctrol system!

20:38 or not

20:38 AWizzArd: yeah sure, there is need for one ;)

20:39 anyway, powr-toc, this issue comes up every few days, but so far svn works very well. No need to switch

20:40 powr-toc: AWizzArd: thought as much... Like I said I didn't mean to stir, I should've known better than to ask :-)

20:46 AWizzArd: powr-toc: btw, if you get your concurrent reads + writes running let me know pls

20:46 te: omg I think I just understood something in clojure

20:46 * te pats himself on the head

20:46 AWizzArd: grats te, what is it?

20:47 te: Basic stuff, refs, derefs

20:47 ive been playing a lot and messing things up, trying to understand how to fit pieces of stuff together

20:47 the idea of #{} is pretty jarring at first tbh

20:48 ayrnieu_: the idea of set literals?

20:48 te: nod

20:48 I just think in general I'm starting to understand the structure.

20:49 It feels a little bit more natural than it did yesterday.

20:49 powr-toc: AWizzArd: I'm just toying about, but if there's interest I might throw it up on github or something

20:50 AWizzArd: sounds good

20:51 powr-toc: AWizzArd: as I said I'm mostly doing it to learn about clojures concurrency primitives... There's a slim chance if I get anywhere that I might use it in production

20:51 lisppaste8: pilkarn pasted "untitled" at http://paste.lisp.org/display/75999

20:52 durka42: eww, java

20:52 :)

20:52 pilkarn: http://paste.lisp.org/display/75999 <- so what should I proxy there?

20:53 JTextArea or JFrame?

20:53 durka42: JTextArea, i think

20:53 powr-toc: I want to focus on correctness first, then wrapping it up in java api, then maybe performance.

20:54 durka42: pilkarn: what does the block marked "instance initializer" do?

20:54 is that an anonymous constructor?

20:57 cp2: 20:52:27 [durka42] is that an anonymous constructor?

20:57 no

20:57 te: wow this is awesome.

20:57 cp2: its just in its own block

20:57 te: (show #{})

20:57 cp2: oh

20:57 te: i know that's pretty meh., but that does me a world of good

20:57 cp2: its not in any method

20:57 durka42: its basically a "quick" way to get something shoved into the default constructor

20:57 durka42: te: c.c.repl-utils is awesome

20:57 senxhnsshp: durka42: iwas wondering the same thing :)

20:57 te: durka42: yeah this is amazing

20:57 :)

20:58 durka42: cp2: proxy can't do that, can it?

20:58 cp2: i dont know

20:58 te: durka42: I can't seem to get my emacs to complete clojure.contrib

20:58 durka42: also those instance variables are going to have to be in a let wrapped around the proxy

20:58 te: any ideas?

20:58 durka42: te: don't use emacs, don't know, sorry

20:58 te: oh no prob

20:58 durka42: err, as in i don't use emacs, not telling you not to

20:58 * te nods

21:01 * durka42 has to run

21:01 te: oh cool -- i see what Lancet is now

21:02 it took me awhile to really start to freaking understand this stuff

21:02 it was like i had sunglasses on

21:03 senxhnsshp: how do I refer to this?

21:03 ayrnieu: senx - in gen-class or in proxy?

21:04 te: so do i understand right, collections are [], (), and {}?

21:04 senxhnsshp: proxy

21:04 ayrnieu: ,(map coll? [[] () {} #{} "" 1 :hi 'hi 1/2])

21:04 clojurebot: (true true true true false false false false false)

21:05 te: booya!

21:05 you rule.

21:09 ,(map coll? [\a])

21:09 clojurebot: (false)

21:09 te: ,(map coll? [[\a]])

21:09 clojurebot: (true)

21:11 pilkarn: how do I refer to this in proxy?

21:11 Chouser: the name 'this' is bound for you.

21:12 pilkarn: so just, this

21:12 Chouser: yes

21:14 Raynes: I wish somebody would make a Clojure wallpaper, I don't feel like it :|

21:14 pilkarn: and super?

21:15 ayrnieu: ,(ancestors String)

21:15 clojurebot: #{java.lang.Object java.lang.Comparable java.lang.CharSequence java.io.Serializable}

21:15 powr-toc: am I right in thinking watchers used to be just functions but are now agents?

21:15 Chouser: pilkarn: proxy-super

21:15 powr-toc: yes

21:16 lisppaste8: pilkarn pasted "untitled" at http://paste.lisp.org/display/76000

21:16 te: haha -- Man I am getting a kick out of clojure

21:17 Chouser: powr-toc: they used to be called 'watches' and worked only on agents

21:17 pilkarn: why am I getting a nullpoinrtexception from that code ? ^^

21:18 i dont really know what im doing but i didnt expect a nullpointer exception

21:18 powr-toc: Chouser: yeah... this is hurting my head... I used to have a watch on an agent, that would then dispatch a message to another agent... now watchers are agents, do I need to do that?

21:19 Chouser: powr-toc: probably not

21:20 hiredman: pilkarn: are you sure JPane shouldn't be JPanel?

21:20 Chouser: powr-toc: might depend on the args you used to pass to the agent action

21:22 hiredman: pilkarn: NPE with proxy usually means clojure cannot resolve the class you are trying to proxy

21:22 resolve? locate? use?

21:22 te: (if "foo" "We are in clojure" "We are in common lisp")

21:22 returns "We are clojure"

21:23 yet (true? "foo") == false

21:23 nevermind im an idiot

21:23 im just trying to get it to print the else without reading ahead

21:23 powr-toc: ok, so here's the deal I have an agent encapsulating a map. Every N modifications I want it to rewrite itself to disk. I don't see why I need the watcher to be an agent, as it doesn't have any state... essentially I just want a callback to do the dispatch to a writer agent.

21:24 are there any simple examples demonstrating watchers??

21:24 Chouser: I have an example. I don't know if its simple. Just a sec...

21:26 powr-toc: (actually that's not strictly true... It serializes everytime the map's size is a ^N... i.e. every Nth add (assuming no removes))

21:27 cp2: ah windows, what a joy you are!

21:28 ayrnieu: te, that would say "We are in clojure" in CL.

21:28 Chouser: powr-toc: http://gist.github.com/32494

21:28 powr-toc: Chouser: cheers mate

21:28 Chouser: not very simple, sorry.

21:29 powr-toc: lol... no a little more complex than I was hoping =)

21:29 Chouser: the code you want is in use-agents

21:30 powr-toc: Chouser: ok.. so I take it there, your watcher-agent has no state?

21:30 Chouser: here's the related blog entry. http://blog.n01se.net/?p=34

21:30 powr-toc: i.e. (agent nil) is just to appease the add-watcher API?

21:30 Chouser: yes, that's right

21:30 rlb: Why would (.update msg-dig buf) work but (.update msg-dig buf 0 5) fail? Clojure complains about not being able to cast java.nio.DirectByteBuffer in the second case (buf), but not in the first. msg-dig is an instance of java.securityMessageDigest.

21:32 Chouser: no such class?

21:32 powr-toc: What is the motivation for making watchers agents?

21:33 Chouser: powr-toc: watches used to be synchronous -- run in the same thread as the agent they were watching

21:33 rlb: Chouser: which class? The program works fine as long as I don't call the update method that takes an offset and count.

21:33 Chouser: powr-toc: when watchers were added to ref, atom, agents, etc. they were made to run on agents so they would be asynchronous.

21:34 powr-toc: apparently rhickey now wants them to be synchronous again -- I'm not sure what that'll do to the api.

21:34 powr-toc: Chouser: yeah I remember that... but isn't it better to allow them to be synchronous, as asynchrony is easily added by passing off directly to an agent

21:35 Chouser: powr-toc: yep, exactly as the issue describes: http://code.google.com/p/clojure/issues/detail?id=80

21:35 powr-toc: i.e. the current design seems to force you through another asynchronous message, even if you don't want it

21:36 lol, rhickey's always ahead in design :-)

21:37 senxhnsshp: http://confusion.tweakblogs.net/blog/1418/why-functional-programming-doesnt-catch-on.html <- and there clojure comes in. I have just "finsihed" an mp3player in it(ok mostly wrapping swing).

21:37 rlb: Is it possible that clojure just doesn't handle the second update method (overload) properly?

21:37 powr-toc: presumably that'll mean the return to a 3 arity function again?

21:39 Chouser: rlb: no

21:39 rlb: I don't have a java.securityMessageDigest class

21:39 senxhnsshp: ah JPanel duh

21:40 rlb: Chouser: http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html

21:40 I'm just using the current clojure .zip and the Debian unstable java packages.

21:41 hiredman: I also get a classnotfound for that class

21:42 Chouser: just missing a dot

21:42 (show java.security.MessageDigest "getInstance")

21:42 rlb: oh, soory.

21:42 s/soory/sorry/

21:42 Chouser: sorry: (show java.security.MessageDigest "update")

21:42 rlb: Right -- (java.security.MessageDigest/getInstance "sha-1")

21:42 Chouser: the method with 3 args takes a byte[] as the first arg

21:43 instead of ByteBuffer like the 1 arg method

21:44 rlb: OK, so clojure isn't matching the Java docs. (Thanks for pointing out "show".)

21:45 hiredman: uh

21:45 java isn't matching the javadocs

21:45 Chouser: (.update (java.security.MessageDigest/getInstance "sha-1") (.getBytes "foo") 0 5)

21:46 cp2: 21:38:39 [rlb] Chouser: http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html

21:46 why are you looking at the 1.4.2 doc

21:46 hiredman: http://www.docjar.com/docs/api/java/security/MessageDigest.html

21:46 cp2: http://java.sun.com/javase/6/docs/api/java/security/MessageDigest.html

21:47 there is an update(byte[])

21:47 rlb: cp2, hiredman: oh, that's obviously my problem.

21:47 cp2: yes :)

21:48 rlb: I had just hit the 1.4 docs first and hadn't gone further.

21:48 Thanks for the cluebat.

21:49 slashus2: ,(array-map 1 1 1 1 1 1 2 2)

21:49 clojurebot: {1 1, 1 1, 1 1, 2 2}

21:49 slashus2: {1 1 1 1 1 1 2 2}

21:50 ,{1 1 1 1 1 1 2 2}

21:50 clojurebot: {1 1, 1 1, 1 1, 2 2}

21:50 Chouser: slashus2: yeah, don't do that. :-)

21:50 slashus2: I was wondering because when I put the previous one into my repl, I get the correct answer {1 1, 2 2}

21:51 Chouser: ,(:a {:a 1 :a 2 :a 3})

21:51 clojurebot: 1

21:51 slashus2: user=> (array-map 1 1 1 1 1 1 2 2)

21:51 {1 1, 1 1, 1 1, 2 2}

21:51 user=> {1 1 1 1 1 1 2 2}

21:51 {1 1, 2 2}

21:51 Chouser: hm, what version of clojure?

21:52 slashus2: The latest svn

21:52 wait

21:52 No, that was the December release.

21:52 sorry

21:52 I thought I had my path setup to run the latest svn.

21:53 Chouser: it was probably a hash-map.

21:53 oh. i guess not

21:53 slashus2: No, (class gives an array map

21:57 Is this correct behavior?

21:59 Chouser: slashus2: http://groups.google.com/group/clojure/msg/7e330411cd04ca71

22:01 slashus2: eh

22:01 powr-toc: Are there any clojure functions to create and write to files?

22:01 or do I just use Java?

22:01 Chouser: powr-toc: clojure.contrib.duckstreams, or just Java.

22:02 by which I mean calling into Java class APIs from clojure code, of course, not actually writing a .java file.

22:02 powr-toc: Chouser: yeah, I knew what you meant :-)

22:03 pilkarn: (proxy [WindowAdapter] []

22:03 (windowClosing [evt] /////// doe sit have to be like that? is it class and then what class-args and then methods for the class?

22:03 Chouser: ok, good. You mentioned dropping to java earlier, and I didn't want to give you any encouragement.

22:03 pilkarn: windowClosing ins a method on WindowAdapter?

22:04 powr-toc: Chouser: Ultimately I'll need to create a java callable API out of whatever clojure code I write... but not yet :-)

22:04 Chouser: powr-toc: gen-class

22:04 slashus2: So, even though there are inconsistencies between hash-map and array-map, it will continue to behave this way?

22:04 Chouser: when you get there

22:05 powr-toc: Chouser: sweet! :-) It should be pretty minimal... probably just one or two classes

22:05 Chouser: slashus2: apparently. You'd prefer the check when building an array-map?

22:05 powr-toc: Chouser: btw... is there any way to create java-docs with genclass or the like? That would be awesome!

22:06 slashus2: Just for consistency sake.

22:06 Chouser: powr-toc: not yet, I think.

22:07 slashus2: ,{1 1 1 1 1 1 2 2 3 3 4 4 5 5 6 6}

22:07 clojurebot: {1 1, 1 1, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6}

22:07 slashus2: ,{1 1 1 1 1 1 2 2 3 3 4 4 5 5 6 6 7 7}

22:07 clojurebot: {1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7}

22:08 slashus2: In practice, it looks strange, especially when it automatically switches when your map gets longer.

22:08 Chouser: why would you build an array-map with duplicate keys?

22:08 senxhnsshp: why is ther eno lazy-conj? how do I lazily add somethign to a vector?

22:08 Chouser: senxhnsshp: vectors aren't lazy

22:09 digash: ,(binding [clojure.core/*print-dup* true] (read-string (pr-str (clojure.xml/parse (java.io.StringBufferInputStream. "<a>A</a>")))))

22:09 clojurebot: java.lang.RuntimeException: java.lang.IllegalArgumentException: No matching method found: create

22:09 digash: isn't it suppose to work?

22:11 Chouser: hm, struct maps do not yet print and readable way.

22:12 powr-toc: has clojure-contrib been updated to avoid lazy-cons yet?

22:13 Chouser: digash: http://clojure-log.n01se.net/date/2008-12-29.html#17:49b

22:13 powr-toc: mostly

22:14 digash: Chouser: are you really a person or AI? :)

22:14 slashus2: Chouser: It seems to only be the case when the array map is being built. When you use assoc, it will not create a duplicate.

22:15 Chouser: slashus2: right

22:17 digash: Chouser: parse/emit should work for me, thank you again.

22:17 powr-toc: my bad... I was pointing at an old clojure-contrib.jar

22:19 * Raynes decides to devote 80% of tomorrow to getting passed page 115 of Programming Clojure and reaching page 200.

22:19 slashus2: I guess the argument from inconsistency won't persuade. Besides, I can't think of a good reason that someone would build an array map with duplicate keys. It would just be nice to apply that assumption to every map.

22:21 * Chouser wonders if bots enjoy strawberries with chocolate.

22:24 lisppaste8: pilkarn pasted "proxy problem" at http://paste.lisp.org/display/76005

22:24 senxhnsshp: cant i let there ^^

22:24 Chouser: no

22:24 do it outside the proxy

22:27 lisppaste8: pilkarn annotated #76005 "untitled" at http://paste.lisp.org/display/76005#1

22:27 senxhnsshp: http://paste.lisp.org/display/76005#1

22:27 thing is i dont really understna dwhat im doing :P

22:32 xavieran: array-map and hash-map should be consistent!

22:33 slashus2: I thought I was the only one.

22:36 CptPicard: .... which means...?

22:39 hmmh so... what's the definition of the keyset of the map?

22:39 is it a set or a multiset..

22:40 slashus2: CptPicard: Would it be better to call it an associative array?

22:40 pilkarn: has anyoen ever displayed a bitma s background ina swinggui? how did you do it?

22:40 CptPicard: maybe... better term..

22:41 but of course the problem is... if you have equivalent keys and many of them, which of the associated items do you get out of the map?

22:41 Chouser: the first

22:41 CptPicard: ok

22:42 Chouser: it's an array, it is scanned for the first matching item.

22:42 ,(:a {:a 1 :a 2 :a 3})

22:42 clojurebot: 1

22:42 slashus2: " collection of unique keys and a collection of values, where each key is associated with one value (or set of values)"

22:42 CptPicard: slashus2, well, arraymap is the latter case.. set of values

22:42 :)

22:43 I guess I can see the rationale for it to be inconsistent... at least you have that sort of functionality when you need it..

22:43 slashus2: CptPicard: That doesn't mean that. The first part exclusively says that it is a collection of unique keys, the second part is talking about what those unique keys may be associated with.

22:44 pilkarn: how do I override a method fo a superclass?

22:44 CptPicard: well the keys are unique, it's just that array-map is an implementation tactic.. :-)

22:45 the map value could just be "some object" otherwise...

22:46 slashus2: Is it true that a hash-map's performance profile is better when a map becomes larger?

22:46 Chouser: (foo :x [1 2 3]) ==> ((:x 1) (:x 2) (:x 3)) What's foo called?

22:46 CptPicard: compared to what?

22:46 slashus2: CptPicard: Compared to an array map.

22:46 CptPicard: sure.. linear vs. constant time

22:47 slashus2: right

22:47 Chouser: inner collections can be seqs or vectors.

22:48 rlb: (Hmm, I must still be doing something wrong -- passing a byte[] to "update/digest" works fine, but trying to use what I think is the same content via a ByteBuffer, doesn't.) Oh well, I'll come back to it later.

22:48 (by doesn't, I mean it generates an incorrect checksum)

22:48 pilkarn: JTextArea textArea = new JTextArea() { super.paintComponent(g); }

22:49 is that calling the paint method on its super-class?

22:52 hiredman: Chouser: I give up, what is it called?

22:53 ,(map (partial list :x) [1 2 3])

22:53 clojurebot: ((:x 1) (:x 2) (:x 3))

22:53 Chouser: It's a real question, not a quiz.

22:53 hm, not bad.

22:53 I have 3, but I don't like any of them

22:54 hiredman: I have no idea what you'd call that

22:54 Chouser: ,(for [value [1 2 3]] [:x value])

22:54 clojurebot: ([:x 1] [:x 2] [:x 3])

22:55 hiredman: ~for

22:55 clojurebot: for is not a loop

22:55 Chouser: oh, actually the other two were wrong.

22:55 hiredman: hmmm

22:55 ~for

22:55 clojurebot: for is not a loop

22:55 hiredman: fine

22:55 hmmm

22:58 pilkarn: ahahahah

22:59 head explosion

23:03 hiredman: , (

23:03 clojurebot: EOF while reading

23:03 hiredman: erp

23:03 ,(map (partial apply list) (apply array-map (cons :x (interpose :x [1 2 3]))))

23:03 clojurebot: ((:x 1) (:x 2) (:x 3))

23:07 danlarkin: I liked (map (partial list :x) [1 2 3]) better

23:10 rlb: This:

23:10 (def d (java.security.MessageDigest/getInstance "md5"))

23:10 (def v (java.nio.ByteBuffer/allocateDirect 1))

23:10 (.put v 0 102)

23:10

23:10 does not give the right digest if you call (.digest d) after that.

23:11 i.e. if you create a file containing a single "f" and run md5sum on it, the result is different.

23:11 However if you use a byte[] rather than a ByteBuffer, it works.

23:12 (assuming I'm not doing something else silly...)

23:14 Chouser: How are you creating the ByteBuffer?

23:14 hiredman: user=> (*1 (repeat :x) [1 2 3])

23:14 ((:x 1) (:x 2) (:x 3))

23:14 rlb: Chouser: see the "def v" above.

23:14 (followed by the .put)

23:14 Chouser: oh

23:15 hm.

23:16 rlb: I though maybe I was printing the contents in hex improperly, so I double-checked the result with a series of (.get digest i) calls.

23:16 It was still wrong.

23:17 However, I'm very new to nio, so I may well be doing something wrong.

23:17 Chouser: well, here's what I've done this weekend: http://gist.github.com/68781 produces http://clojure.googlegroups.com/web/issues-graph.png

23:18 danlarkin: Ooooooooo

23:18 rlb: Chouser: nice.

23:19 Chouser: rlb: how are you printing the byte array?

23:19 digash: Chouser: very cool, i needed an example how to use JChart.

23:20 rlb: Chouser: I was just using a per byte print, but then I realized java only has signed bytes, and switched to this:

23:20 (which may be wrong)

23:20 (dorun (map

23:20 (fn [x] (println (bit-and x 255)))

23:20 (seq (.digest d))))

23:20 (println)

23:20

23:21 slashus2: Chouser: Is there a reason that you used (Integer. n) instead of (int n) ?

23:21 line 40-41

23:22 Chouser: ,(int "5")

23:22 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character

23:22 slashus2: ouch

23:22 Chouser: hm, "close" should be "total"

23:26 rlb: I guess I can just switch to byte[]. I was trying to use nio because I had the impression that it was more efficient, but I can worry about that later.

23:27 pilkarn: how do i calc n log n when n = 1000000

23:28 user=> (* 1000 (Math/log 1000))

23:28 6907.755278982137

23:28 is that correct?

23:29 Chouser: rlb: is there a newline in your test file?

23:31 ,(import '(java.security MessageDigest) '(java.nio ByteBuffer))

23:31 clojurebot: nil

23:31 Chouser: ,(let [d (MessageDigest/getInstance "md5"), v (ByteBuffer/allocateDirect 1)] (.put v 0 102) (.update d v) (apply str (map #(format "%x" %) (.digest d))))

23:31 clojurebot: "8fa14cdd754f91cc6554c9e71929cce7"

23:31 gnuvince_: pilkarn: assuming it's log and not lg, yes.

23:31 rlb: Chouser: no, and I double checked with od.

23:32 Chouser: $ echo -n f | md5sum ==> 8fa14cdd754f91cc6554c9e71929cce7 -

23:33 rlb: Chouser: hang on -- I think I may have gotten it.

23:33 I may have misunderstood a bit about messagedigest...

23:37 So after each read/update, would it be correct to call .clear on the buf to reset it for the next read?

23:38 Chouser: I don't know, sorry.

23:39 cooldude127: please kill me, why is finding a path with a BFS so damn unnatural

23:39 rlb: No problem -- I appreciate the help. Though I think perhaps I should stop soon. I'm overlooking obvious mistakes.

23:48 pilkarn: how can I reimplement a method for a class?

Logging service provided by n01se.net