#clojure log - Aug 24 2009

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

2:09 hiredman: ~ping

2:09 clojurebot: PONG!

3:02 alinp: hi

4:23 liwp: ~ping

4:23 clojurebot: PONG!

4:28 Neronus: And clojurebot wins the game

5:30 raphinou: HI

5:31 I'm still debugging this code: http://paste.lisp.org/display/85858

5:32 how can I know the type of the arguments passed to an object's method? (it is addListener in the pasted code)

5:36 Licenser_: morning everyone

5:36 raphinou: HI Licenser_

5:38 Licenser_: hi raphinou I would love to help but I'm newer to clojure then you I geuss ;)

5:38 raphinou: :-)

5:39 no problem Licenser_ , I'm searching further

5:40 Licenser_: some somart person here told me using (.. is uglish it's better to use (.<function> but I don't know if that is of any relevance for you

5:41 raphinou: no Licenser_, the code is running actually, but it's the type of arguments passed that seem to cause problem

5:41 woodz: raphinou: the type function does this for you: (type "foo") --> java.lang.String

5:41 raphinou: I also had the advice to use (-> ) rather than (.. )

5:42 woodz: the problem is that it is not a clojure function I try to debug, but a method on a java object

5:42 I'm looking at jswat, but as I'm new to the java platform I'm progressing slowly to put all pieces together

5:42 _crc: raphinou: A possibly useless suggestion: Can you try type hinting, the second argument to the addListener. I see that EventSignal has two addListener methods with same arity but varying types.

5:43 raphinou: _crc: yes, good suggestion. I'll try that!

5:43 woodz: Ah, right. You could use Java's reflection API to get a Method object, and call getParameterTypes on that.

5:44 _crc: I don't know how the clojure compiler resolves overloaded method calls. I guess people that know are asleep right now :)

5:45 raphinou: :-)

5:45 I'm not sure how I add a type hint on the proxy object. Alls type hint I find are in the definition of a function.

5:47 hmm, just found (cast )

5:50 Licenser_: I really would love how they handle closures in clojure

5:50 insert a 'to know' in there :P

5:56 tomoj: Licenser_: what do you mean exactly?

5:57 ,((let [a 2 b 3] (fn [] [a b])))

5:57 clojurebot: [2 3]

5:58 Licenser_: tomoj: I mean compiler wise

5:58 tomoj: oh, I see. I dunno about the internals

5:58 Licenser_: because I've trouble with that :P it's a really tricky thing for a compiler/interpreter

6:00 raphinou: _crc: shouldn't I be able to cast the proxy object to the expected class ?

6:05 _crc: raphinou: Type hinting didn't solve the issue?

6:06 raphinou: _crc: can I do type hinting on a method that is defined in the java class?

6:06 tomoj: Licenser_: a naive stack of bindings isn't sufficient?

6:06 raphinou: all type hinting I've found are in the definition of clojure functions

6:06 Licenser_: tomoj: I write on a VM/Interpreter/Compiler set since a while and closures are the thing that is most complicated for me / causes the most problems

6:07 _crc: well, what i mean is something like this (.. line-edit enterPressed (addListener wapp #^Signal$Listener (proxy [Signal$Listener]....

6:07 I am not even sure that works. But worth a try :)

6:08 raphinou: _crc: I'll try. What I tried without success is (.. line-edit enterPressed (addListener wapp (cast Signal$Listener (proxy [Signal$Listener]..

6:10 seems equivalent to the (cast )

6:11 exact same error

6:13 Chousuke: cast is pretty much a no-op in clojure

6:14 it just checks whether the object is treatable as whatever you're casting to.

6:15 _crc: raphinou: Hmm.. are you sure the first argument type is what it expects. I mean, the wapp object.

6:16 Chousuke: hmm

6:17 you're using .. there so it's (.addListener (.enterPressed line-edit) wapp ...)

6:17 raphinou: yes, the wapp is fine as I instanciate it as a WApplication, and it's inheriting from WObject

6:18 _crc: Chousuke: The .. operator doesn't need the (.method..)

6:18 raphinou: Chousuke: lemme check

6:19 Chousuke: _crc: I know, I just meant that's what it expands to

6:19 and it looks dubious

6:19 does (.enterPressed line-edit) really have an .addListener method?

6:20 .enterPressed looks like it returns a boolean but I guess it could be returning an event :/

6:20 raphinou: yes

6:20 _crc: The error apparently is "No matching method found: addListener for class eu.webtoolkit.jwt.EventSignal"

6:20 raphinou: enterpressed returns an SignalEven which such a method

6:21 Chousuke: Clojure REALLY should print the parameter types with that exception ;(

6:22 _crc: Chousuke: I agree.

6:22 raphinou: Are you working on trunk?

6:22 raphinou: I did a checkout last week and compiled it

6:23 I didn't look further which version resulted in compiled form

6:46 Licenser_: The expetions really give very very little helpfull information

6:46 It does not even tell you where they occur :/

6:51 tomoj: in slime you get a backtrace

6:52 and you can get a backtrace other ways too but I don't know how

6:54 Licenser_: slime is that emacs thingy?

6:57 tomoj: yeah

7:27 ole3: test

8:02 alinp: hi

8:02 is there a foldr in clojure ?

8:02 reduce has foldl functionality, at least this is what I noticed

8:03 Neronus: alinp: I don't think so, as sequences are possibly infinite

8:04 alinp: ok, in this case it seems ok

8:04 Chouser: I don't think there's a foldr, though you could use 'reverse;

8:04 alinp: thanks

8:04 that should do the trick :)

8:04 Chouser: or if you're working on a vector, maybe rseq

8:06 alinp: rseq is not returning a lazy seq

8:06 right ?

8:06 at least this is what the doc says

8:06 Chouser: it probably is, but it's over a non-lazy thing like a vector or map

8:06 alinp: ,(doc rseq)

8:06 clojurebot: "([rev]); Returns, in constant time, a seq of the items in rev (which can be a vector or sorted-map), in reverse order. If rev is empty returns nil"

8:06 alinp: yeah, indeed

8:07 my q had no point, sorry :)

8:08 Chouser: so it's a seq but, right, calling it lazy doesn't mean much even if its true.

8:09 rhickey: Chouser: which patch files do I need to apply to test chunked for/concat? could you paste the timing code you were running?

8:10 Chouser: chunked-concat.diff and chunked-for.diff

8:13 To test the timing I kept the old definition of 'for' as 'for1'

8:18 rhickey: Chouser: what code had a 2x variance?

8:20 Chouser: that's on the other computer. gimme a minute...

8:22 rhickey: Chouser: don't worry about it - I've got it running now here

8:22 the 2x diff has to do with whether or not you get a gc during the run I think

8:23 Chouser: ok. the variance was not between the two versions, it was the same version on subsequent runs.

8:23 yeah, ok

8:23 tomoj: is chunking what causes this?:

8:23 ,(dorun (take 4 (map println (range 10))))

8:23 clojurebot: 0 1 2 3 4 5 6 7 8 9

8:24 tomoj: seems to go over in increments of 32

8:25 rhickey: tomoj: ?

8:25 tomoj: (e.g. if you do that taking 4 and (range 100), it prints 0-31, while if you take 33, it prints 0-63

8:27 rhickey: tomoj: yes

8:27 Chouser: (time (into [] (for1 [a (range 1e6) :when (odd? a)] a)))

8:28 I was doing "into []" in an attempt to get a chunked consumer (unlike doall or last)

8:29 rhickey: reduce is a chunked consumer too

8:29 Chouser: ah, of course.

8:30 tomoj: so due to chunking is it generally bad to have lazy seqs which cause side-effets on consumption?

8:30 Chouser: yeah, that's more stable.

8:31 tomoj: if your lazy seq isn't chunked, nothing should have changed.

8:32 tomoj: ah, but range for example generates a chunked seq, then?

8:32 Chouser: tomoj: the "problem" with your example is having a side effect in 'map', which has never been recommended.

8:32 rhickey: tomoj: there will be a seq1 (name TBD) which will force non-chunked seqing of a possibly-chunked seq

8:32 tomoj: that's what I told the person asking about this the other day, I recommended doseq instead

8:32 but then I saw it in ants.clj

8:33 Chouser: tomoj: exactly. doseq also does chunking now, but if you guard a loop with :while then your body will not be called when it shouldn't.

8:33 rhickey: tomoj: you saw the chunked side effect problem or just map of side-effecting fn?

8:33 tomoj: just a map of side-effecting fn

8:34 no chunking problem I believe

8:34 nah, cus the send-off needs to go to all ants anyway

8:38 Chousuke: hmm, why doesn't the clojure dev group have the lambda picture as its logo? :(

8:52 lisppaste8: raphinou_ annotated #85858 "untitled" at http://paste.lisp.org/display/85858#1

8:52 raphinou: it seems the wrong addListener method is called (same arity, different signature)

8:53 any idea how I can tell that I want the other one to be run?

9:01 lisppaste8: Chouser pasted "'for' timings" at http://paste.lisp.org/display/85959

9:02 Chouser: so I guess the new 'range' cost a bit, but allows for better optimizations down the chain.

9:08 Chousuke: gah.

9:09 I was wondering why paredit behaved weirdly. then I noticed it was using an old version I had accidentally installed with elpa :P

9:09 clojurebot: http://clojure.org/rationale

9:35 Chousuke: hm, neat.

9:36 the next milestone for my reader was to read core.clj without exceptions. Turns out it already can :P

9:37 I doubt evaling things is going to go so well, though :/

9:40 LauJensen: Oh my. Did the previous discussion on chunks mean that when I call (take n coll) I cant count on getting n items back ?

9:40 Chouser: LauJensen: nope, nothing of the sort

9:41 LauJensen: phew - Got a little scared there for a bit

9:54 Chouser: could range provide a sort of lazy chunk?

9:55 override .nth to do the math on demand rather than allocate an array?

9:56 Chousuke: hm

9:56 weissj: what's the easiest way to iterate thru a list of function symbols, and call each one with the same arg?

9:57 ,(for [myfn '(inc dec)] (println (myfn 1)))

9:57 clojurebot: (nil nil)

9:57 weissj: ,(for [myfn '(inc dec)] (myfn 1))

9:57 clojurebot: (nil nil)

9:57 Chousuke: I got as far as evaling the first 109 top-level forms of clojure.core

9:57 rhickey: Chouser: chunk consumers need the chunk size in order to allocate their own chunks

9:57 Chouser: ,(map #((resolve %) 5) '(inc dec))

9:57 clojurebot: (6 4)

9:57 Chousuke: it breaks on / :)

9:57 Chouser: Chousuke: not bad!

9:57 Chousuke: which is not surprising at all, considering my symbol parsing is rather primitive still.

9:57 Chouser: rhickey: sure, it would still be Chunks of size 32, but instead of ArrayChunks they'd be RangeChunks

9:59 Chousuke: now my problem is that the error message is not very helpful :/

9:59 rhickey: Chouser: ah, so not really about laziness, just 'virtual', sure

9:59 Chouser: right, just for performance

10:00 rhickey: I thought you wanted to solve tomoj's chunked laziness granularity problem

10:00 Chouser: ah, no. that's not a problem. :-)

10:00 Chousuke: it simply says "Can't refer to qualified var that doesn't exist"

10:00 fdaoud: hi all

10:00 rhickey: actually, it is a problem, and a tricky one, not for side effects but for expensive calculations

10:00 Chousuke: and while I suspect / is the problem, I'm not sure what's wrong with it

10:01 fdaoud: hey, there is the Clojure elite here!

10:02 Chouser: fdaoud: welcome

10:03 fdaoud: thanks Chouser....congrats rhickey and all for Clojure. I'm reading Stu's book. Very cool stuff.

10:04 I've been interested in functional programming for years, but Clojure is the first time I see it all come together

10:06 Chouser: I just wanted macros and libraries, but rhickey foisted all this immutable stuff on me.

10:06 rhickey: :)

10:07 fdaoud: Now if I can integrate Clojure with Stripes, I'll be all set :)

10:16 Chousuke: hmm

10:17 ,(map namespace ['foo (symbol "foo")]); curious behaviour

10:17 clojurebot: (nil nil)

10:17 Chousuke: huh. I get "" for the second case

10:17 hmm...

10:18 no wait, got confused

10:19 ,(map namespace ['/ (symbol "/")]); this is when it happens for me :/

10:19 clojurebot: (nil "")

10:21 Chousuke: ~def symbol

10:22 Chouser: ,(range 1/2 5 1)

10:22 clojurebot: (1/2 3/2 5/2 7/2 9/2)

10:22 Chouser: ,(range 1/2 5)

10:22 clojurebot: (1/2 3/2 5/2 7/2 9/2)

10:22 Chousuke: looks like a bug in Symbol/intern

10:22 Chouser: hm. In clojure 1.0 the latter gives (0 1 2 3 4)

10:23 Chousuke: if the name contains a /, it does "return new Symbol(nsname.substring(0, i).intern(), nsname.substring(i + 1).intern()"

10:24 which means the namespace will become "" instead of nil

10:45 raphinou: I'm lost here: I have a java object with the method addListener. Arity of addListener is 2, and it has 2 definitions differing by the type of its arguments. It seems the wrong one is called and I get an IllegalArgumentException....

10:46 is there a way to specify the method to be used?

10:46 the second argument is a proxy object, which can not be casted to the type expected by the method

10:50 Chouser: raphinou: I looked at your paste briefly, but didn't see what could be causing your problem.

10:51 proxy self-hints with the class you're extending, Signal$Listener

10:51 raphinou: Chouser: I think the code is fine, but the way the java method to run is chosen is picking the wrong one. Ha, ok for the self-hint. I didn't know that

10:52 Chouser: from your stack frame it lokos like it's found the right class for wapp, jwt.EventSignal

10:53 oh, wait -- where's your WObject?

10:53 raphinou: it's the wapp

10:53 Chouser: oh, right ..

10:54 raphinou: I'm shooting in the dark here, but you might try turning on reflection warnings first, and make sure you're getting the call resolved at compile time.

10:54 that sometimes helps bring out the real issue.

10:55 raphinou: hmm, I read something about reflection warnings this morning. Will try to find it back. Thx for the hint, I'll try that

10:55 Chouser: (set! *warn-on-reflection* true)

10:55 raphinou: ha, thx :-)

10:56 Chouser: insert that before the top level form that contains your erroring call

10:56 the re-load or re-eval or re-compile or whatever you're doing

10:56 then

10:56 raphinou: call to addListener can't be resolved!

10:56 you're righ Chouser

10:56 Chouser: ok, not exactly shocking, but not an error in itself

10:57 I guess try hinting the wobj?

10:57 raphinou: ok, I'll try that

10:57 Chouser: er, wapp

10:58 is that the only reflection warning, or are there others, like for enterPressed?

10:58 Chousuke: ~def mexpand-all

10:59 raphinou: Chouser: only warning, and type hint or cast do not resolve it

11:00 Chousuke: hmmhm

11:00 Chouser: doesn't resolve the warning or the runtime error?

11:01 raphinou: both

11:02 cark: raphinou : you're still stuck at the same point ?

11:02 raphinou: yes cark

11:02 cark: =(

11:03 Chouser: ok, so try (addListener #^WObject wapp #^Signal$Listener (proxy ...))

11:04 the latter hint shouldn't be necessary, so I don't actually expect that to fix it.

11:04 if it doesn't, it might be time to unpack that .. so we can see what's going on.

11:05 (let [sig (.enterPressed line-edit)] (.addListener #^EventSignal sig #^WObject wapp (proxy ...))

11:06 that let form really should not produce any reflection warnings.

11:06 raphinou: ok

11:07 Chouser: rhickey: why does IChunk have a reduce? Does it really perform that much better than having the reduce fn do a general loop on each chunk?

11:11 raphinou: same problem with type hints. chouser, you want me to put the let in the code of the app, that's it?

11:12 Chouser: yeah, using that 'let' instead of your .. form ought to remove any reflection warning from that line.

11:12 you're saying it still generates a reflection warning?

11:12 for addListener?

11:12 rhickey: Chouser: I don't recall, but I presume so, else I thought many would be writing that same loop over and over, or tempted to call reduce itself in their chunk fns

11:13 raphinou: both warning and exception are still there Chouser

11:13 Chouser: yeah. writing my first IChunk implementation here and I've got a bug in my reduce. :-P

11:14 raphinou: bleh. try the hint on 'proxy' too then? If it still fails I'd start to doubt the javadocs

11:17 lisppaste8: raphinou_ annotated #85858 "let to remove reflection warning" at http://paste.lisp.org/display/85858#2

11:17 raphinou: I posted the let as I still get the warning :(

11:18 I hope I'm not doing something stupid and wasting your time....

11:20 Chouser: do you have clojure-contrib handy? repl-utils?

11:21 (show EventSignal "addListener")

11:21 raphinou: clujure-contrib yes

11:22 repl-utils I don't know

11:22 Chouser: just try that 'show' at the repl and see if it lists the addListener method you're trying to call

11:22 (use 'clojure.contrib.repl-utils)

11:22 raphinou: hem, ok, just found out..

11:24 lisppaste8: raphinou_ annotated #85858 "show EventSignal addListener" at http://paste.lisp.org/display/85858#3

11:24 Chouser: ...and there's the problem

11:24 oh

11:24 wait

11:24 bah

11:24 (show EventSignal 0)

11:26 cark: mhh i should be using repl-utils more

11:26 lisppaste8: raphinou_ annotated #85858 "show EventSignal 0" at http://paste.lisp.org/display/85858#4

11:28 krumholt: can someone help me understand what happens when i do ('+ 1 2) why does a symbol take arguments?

11:28 Chouser: ok, I'm completely stumped. I don't see how that method can exist and yet your call to it fails to resolve.

11:29 raphinou: :(

11:29 Chouser: krumholt: symbols look themselves up in a map when called.

11:29 ,('+ {'foo 1, 'bar 2, '+ 3})

11:29 clojurebot: 3

11:30 Chouser: just like keywords do. A second arg is allowed for when the key is not found.

11:30 ,('+ {'foo 1, 'bar 2, '+ 3} :default-something)

11:30 clojurebot: 3

11:30 Chouser: ,('+ {'foo 1, 'bar 2} :default-something)

11:30 clojurebot: :default-something

11:32 cgrand: raphinou: try putting the proxy in a local and still fully hint the addListener call

11:33 raphinou: ok, trying

11:33 krumholt: Chouser, so the first argument to a symbol is a map to lookup its value and the second is the default value?

11:33 Chouser: krumholt: right. if the first arg is not a map, it returns the second arg or nil

11:33 ,('+ 5)

11:33 clojurebot: nil

11:35 krumholt: Chouser, ok thanks. i just stumbled upon this and wanted to understand it.

11:35 Chouser: krumholt: keywords act the same, and that pattern is rather more common

11:35 raphinou: cgrand: I get a class cast exception:

11:35 clojure.proxy.java.lang.Object$Listener cannot be cast to eu.webtoolkit.jwt.Signal$Listener

11:36 cgrand: paste?

11:36 raphinou: coming

11:37 lisppaste8: raphinou_ annotated #85858 "class cast exception" at http://paste.lisp.org/display/85858#5

11:38 raphinou: but warning has disappeared

11:39 cgrand: my guess that the warning was caused by macroexpansion eating the type hint on proxy

11:39 clojurebot: proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.

11:40 Chouser: but the ClassCastException doesn't make any sense, does it?

11:40 cark: looks like a bug to me

11:41 cgrand: no :-(

11:42 raphinou: would anyone be interested in a tarball with my code and all jars it depends on? It's about 8Mb. I can easily put it online

11:43 Chouser: raphinou: yeah

11:43 raphinou: ok, it's coming!

11:43 cark: maybe proxy doesn't know how to handle nested interfaces ?

11:44 Chouser: this is how the Greeks defeated Troy.

11:47 cark: I was wondering the same thing, but I guess it's not that simple. This looks ok: (supers (class (proxy [Object javax.swing.text.AttributeSet$ColorAttribute] [])))

11:48 Chousuke: hmm

11:48 It looks like my reader can read clojure.core, but there are other problems with it

11:48 redefining clojure.core on the fly causes slime to barf, for example :P

11:49 after it gets to the point where it redefines print-method, something happens and *boom*

11:51 raphinou: okn the tarball is at http://www.raphinou.com/rb.tar.bz2

11:51 I put a README in it to say how I run it

11:55 Chouser: should I get that ClassCastException?

11:58 raphinou: yes Chouser

12:00 lisppaste8: Chouser annotated #85858 "no error for me?" at http://paste.lisp.org/display/85858#6

12:01 raphinou: I get the error when requesting page at http://localhost:8080

12:02 it prints my user agent, and the I have the exception printed

12:02 Chouser: ah, ok, I got it.

12:12 cgrand: could it be a classloader mess? two Signal$Listener classes loaded by two classloaders? (shooting in the dark)

12:13 raphinou: this is beyond my java knowledge, I have no idea

12:13 clojurebot: this is not a bug

12:22 rhickey: clojure.proxy.java.lang.Object$Listener looks funky

12:23 cgrand: raphinou: wow, your listener effectively implements Signal1$Listener and not Signal1$Listener: I think proxy caching got confused

12:23 "and not Signal$Listener"

12:23 raphinou: ok

12:23 Chousuke: hmmh

12:24 Chouser: Signal$Listener inherits only from SignalImpl$Listener

12:24 Chousuke: apparently it's not possible to redef clojure.core in its entirety by reading and evaling the file. :/

12:24 Chouser: but the generated proxy class inherits from #{eu.webtoolkit.jwt.SignalImpl$Listener eu.webtoolkit.jwt.Signal1$Listener clojure.lang.IProxy java.lang.Object}

12:24 Chousuke: the repl barfs when you redef print-method

12:25 rhickey: Chousuke: yes, could you please submit an issue for that?

12:26 Chouser: you can go ahead with chunked concat/for

12:27 Chousuke: okay. I'm using my own reader here though

12:27 Chouser: where do SignalImpl$Listener and Signal1$Listener come from?

12:27 Chousuke: but I suppose the problem is with eval

12:27 Chouser: rhickey: ok, thanks.

12:27 rhickey: Chousuke: try clojure's same prob

12:27 cgrand: Here is the culprit:

12:27 be.nsa.server=> (proxy-name Object [Signal$Listener])

12:27 "clojure.proxy.java.lang.Object$Listener"

12:27 be.nsa.server=> (proxy-name Object [Signal1$Listener])

12:27 "clojure.proxy.java.lang.Object$Listener"

12:27 Chouser: cgrand: ah, nice.

12:28 cgrand: so the second call to proxy retieves a cached class

12:28 raphinou: wow, good catch

12:29 Chouser: is there a limit on class name length? seems like proxy-name should include (and/or hash) the full package name of all implemented interfaces too

12:30 does newnew use something similar?

12:30 raphinou: ok, so the problem happens if multiple nested interfaces have the same name?

12:30 cgrand: and should escape $ too

12:31 rhickey: cgrand: $ is an ok name component

12:33 raphinou: if I only define the second listener, and only import Signal$Listener, I still have the same problem

12:33 cgrand: I meant: if we are going to include full names, we should escape the $ characters in the full names to prevent collisions on pathological worst cases

12:34 rhickey: I think we should just use lastIndexOf '.' instead of getSimpleName

12:35 Neronus: Chouser: Class name lenghts have to fit into CONSTANT_Utf8_info in the constant pool. And the maximum length of such an entry is 2^16

12:35 Class names have to fit into that entry, not their lengths

12:36 cgrand: if one uses two frameworks which each defines a Listener interface, proxy would still confuse them since it wouldn't include the package

12:36 rhickey: this is another why '.' as nested class separator is weak, and why the $ is used for the real JVM name

12:37 cgrand: true, but I'd rather append the hash of full names than have a giant name

12:38 cgrand: rhickey: ok

12:50 weissj: does clojure have a facebook page? (like scala's here http://www.facebook.com/pages/Scala/62722535767?ref=mf )

12:51 would be nice if i could make myself a 'fan of' clojure for my programmer friends to see

12:52 drewr: there's a "Finding Clojure" group

12:52 and now there's apparently a "Clojure" group

12:52 weissj: drewr: yeah i saw that. but groups don't work the same as company/famousperson pages

12:55 Chousuke: rhickey: I created a ticket for the repl issue. I also created one for (namespace (symbol "/")) returning "" instead of nil (with patch)

13:07 cgrand: raphinou: in the mean time, you could work around by specifying a second useless interface (just to generate another name)

13:17 raphinou: cgrand: in java you mean?

13:17 is there a ticket for this issue btw, so I can follow it and try again.

13:19 cgrand: raphinou: eg replace (proxy [Signal$Listener] by (proxy [Signal$Listener Comparable] it should work

13:19 raphinou: ho, I see

13:20 but how comes the same problem arises when I import and define only the Signal$Listener ?

13:21 it works by specifying a second interface. thx!

13:21 and thx everyone who looked at this problem!

13:22 hmm, it worked when adding the second interface when I had the first listener commented....

13:23 cgrand: which first listener? (proxy [Signal1$Listener] ?

13:24 raphinou: (.. (WPushButton. "Greet me" root) clicked (addListener....

13:25 hmm, wait, checking I'm working on the right version....

13:30 ok, it's working fine now...

13:30 right on time, I need to go. bye!

13:31 cgrand: rhickey: should I open a ticket for the proxy-name bug?

13:33 rhickey: cgrand: sure

13:33 thanks

13:43 devinus: i keep hearing people say that clojure has no objects

13:43 but other people saying that's BS

13:43 which one is it?

13:43 i'm assuming "objects" are just represented entirely different than in your standard OO language

13:43 Neronus: ,(Object.)

13:43 clojurebot: #<Object java.lang.Object@e62f6>

13:44 Neronus: there you go :)

13:44 LauJensen: devinus: Read "Object Orientation is overrated" http://clojure.org/rationale

13:45 Neronus: While there are objects (everything is a java object, except the primitives), there is no need to think of objects except when doing java interop

13:46 fdaoud: Hi all. Does anyone know how to have a context path in compojure? I can't seem to find the info. The examples I find all have the app deployed under the root path.

13:47 Chousuke: gah.

13:47 Assembla sent me some mail and apparently it triggers a bug in Mail...

14:00 arbscht: fdaoud: you can associate servlets to non-root request paths in run-server, if I understand you correctly. also, git HEAD has `with-context', which trims context prefixes from the request

14:00 fdaoud: pop into #compojure to discuss it further if you want :)

14:00 fdaoud: arbscht: thanks for the info! I didn't realize compojure had its own channel :)

14:18 rhickey: cgrand: your master still contains Arrays.copyOf calls

14:29 jensli: Hi all!

14:29 Can anyone recomand a book? Programming Clojure or The Definitive Guide to Clojure?

14:29 Maybe the latter isnt out yet...

14:30 cgrand1: it should be in print at the end of year

14:31 Chouser: right now the definitive guide is Programming Clojure. :-)

14:32 LauJensen: Who's writing 'the definitive guide' ?

14:33 Chouser: LauJensen: http://www.www.friendsofed.com/book/view/9781430272311

14:34 LauJensen: Luke Vanderhart, never heard of him

14:34 Chouser: he's posted to the group a couple times

14:35 LauJensen: What makes this book 'definity' and programming clojure, not ?

14:35 (since he's saying its the first)

14:35 hiredman: still haven't finished programming clojure

14:35 LauJensen: it's bigger?

14:35 LauJensen: oh thats right, he's american :)

14:36 jensli: More pages but less weight!

14:36 In Defeniteve guide

14:36 Chouser: I guess "a few" is understating it a bit. google say 45 posts.

14:37 He apparently works with the DC study group

14:37 LauJensen: I feel a soap coming on "Chouser Chen - Internet stalker"

14:38 jensli: This language running amok? Soon someone unheard of is going to release 2.0.

14:41 LauJensen: jensli: Why do you think so ?

14:41 hiredman: what?

14:41 ~what?

14:41 clojurebot: do you ? what is the benefit of lazy sequences

14:43 jensli: Someone you havent hear of released the Definitive guide, it might go on in that way...

14:44 LauJensen: Dont worry, Chouser has got it covered

14:44 * Chouser blinks

14:44 * Neronus has some other nice book titles: What about "Clojure gems" or "The art of programming clojure"... or "A gentle introduction into clojure" :)

14:45 Neronus: Or clojure for dummies

14:48 jensli: *** will that write "A brutal intro to clojure"

14:49 How does dynamic typing affect the possibility of IDE support?

14:49 Would it be possible to write a good rename tool for clojure?

14:49 For example...

14:50 rhickey: jensli: IntelliJ Clojure plugin does good renaming already

14:52 jensli: Allright, has to try that, have only played with it in eclipse, it rather spartan.

14:53 technomancy: it should be doable on top of slime's xref functionality, but afaik nobody's hooked it up

14:55 drewr: technomancy: I finally got swank loaded inside a persistent, non-repl jvm process

14:58 http://github.com/drewr/clot/commit/902272d69133e88b28147407e089733292511af8#L2L11

14:58 technomancy: drewr: slick!

14:59 drewr: swank really wants to be run from a repl, so you have to fake it

14:59 the repl stuff in clojure.main made it very easy -- thanks to whoever did that (scgilardi?)

15:35 weissj: anyone have any advice on how to get my repl to re-load java classes i'm developing without having to restart the jvm?

15:37 Chouser: generally the jvm doesn't allow loading a new definition for an existing class

15:38 clojure lets you redefine any namespace, function, or proxy, though. You really need to reload a named Java class?

15:38 weissj: Chouser: hm ok, i had a feeling that wasn't possible (or easy at least). It's just clojure code that easy to change and debug in the same repl

15:38 Chouser: these are classes written in .java?

15:38 weissj: Chouser: yeah, my project here is basically a scripting environment for java classes

15:39 the script i can debug and update in the same repl, but if i have to change a java class,i have to restart the repl

15:39 hiredman: ~google java rebel

15:39 clojurebot: First, out of 174000 results is:

15:39 Chouser: http://www.zeroturnaround.com/javarebel/

15:39 clojurebot: JavaRebel | ZeroTurnaround.com

15:39 http://www.zeroturnaround.com/javarebel/

15:39 hiredman: nice

15:39 Chouser: yeah. you could try that, though I've not heard any reports of people using it with clojure

15:40 weissj: cool, i'm going to try that out

15:41 oh. hm, it's not really free

15:53 Chouser: rhickey: newnew doesn't currently try to create stable classnames, but will that change to support AOT?

15:56 stable nor package qualified.

15:57 Licenser__: out of couriosity, what is newnew?

15:58 Chouser: Licenser__: I wrote a little about what it's for here: http://blog.n01se.net/?p=41

15:58 Licenser__: *reads*

15:59 Chouser: Licenser__: there's also a link there to rhickey's notes on the subject. There's also a branch "new" in the github repo with the work in progress.

15:59 Licenser__: ah okay new is a branch :)

16:01 hmm don't you have the hen egg problem when implementing a language in itself?

16:01 You will need a working implementation to implement it right?

16:01 Chouser: sure, but we already have one. The hen, probably.

16:01 Licenser__: But it would mean when somethign changes to change it twice, for the hen and for the egg that gives a new hen :P

16:02 Chouser: yep. standard compiler procedure.

16:04 danlei: Licenser__: you could always hand-compile (theoretically)

16:04 Licenser__: Chouser: hmm didn't knew that :) I'm quite new to compiler building :P

16:05 hiredman: whee

16:05 Chouser: Licenser__: the "normal" way to build gcc, for example, is to compile a minimal gcc using whatever c compiler you have handy.

16:05 Licenser__: ah I didn't knew that :)

16:05 I learn a lot here it seems

16:05 hiredman: the gcc build happens in stages, I believe

16:05 Licenser__: hmm clojurescript is very interesting too

16:05 hiredman: the last stage is to compile gcc with gcc

16:05 Chouser: Licenser__: that minimal compiler uses only the most widely supported C features so it's likely to work with your OS vendor's own compiler, or whatever.

16:07 you go through two or three stages of using the previously built compiler to build a more featureful compiler needed for the next stage.

16:07 Licenser__: ah

16:07 Licenser_: I like this idea, it sounds very cool

16:07 hiredman: http://gcc.gnu.org/wiki/Top-Level_Bootstrap

16:07 Licenser_: clojure-in-clojure

16:08 Chouser: you go through two or three stages of using the previously built compiler to build a more featureful compiler needed for the next stage.

16:08 Licenser_: You people are smartish :P

16:08 Chouser: er

16:08 you go through two or three stages of using the previously built compiler to build a more featureful compiler needed for the next stage.

16:08 Licenser_: ^^

16:08 Chouser: bah

16:08 Licenser_: You like to say that don't you?

16:08 Chouser: by the end you can have a gcc that was built from C source using all of gcc's own extensions and with gcc's most advanced optimizations.

16:08 sorry

16:08 Licenser_: :P just teasing

16:09 makes kind of sense, oddly enough

16:09 Chouser: anyway, clojure-in-clojure isn't likely to be quite that extreme. For one, the .class files are already portable to anywhere that has a JVM, so you wouldn't generally need to distribute the original .java

16:10 danlei: first lisp was hand-compiled by steve russel, btw

16:10 hiredman: wow

16:10 hand compiled from lisp?

16:10 danlei: yes

16:11 hiredman: I guess it bust have been

16:11 jeez

16:11 Licenser_: I like to compile things myself, and I think distributins like gentoo would not be happy to only get .class

16:11 He had a lot of time and was very boored?

16:11 danlei: he took mccarthys "universal LISP function" and translated the whole thing by hand

16:11 Neronus: FWIW "LISP in small pieces" is probably enough to get one started (though I still have to read it :))

16:11 technomancy: lisp was a lot smaller back then. =)

16:11 and he was a grad student

16:11 Chouser: Licenser_: I'm sure we'll keep the .java version around, and probably not just in the github history

16:11 hiredman: just have a shellscript that emits jvm bytecode

16:11 danlei: (mccarthy actually didn't even WANT that :)

16:13 Chousuke: I think it might be good to ship at least one version of Clojure with both the Java bits and the c-in-c bits whenever we get to that stage.

16:14 then it could be used to bootstrap itself, and the java bits could be dropped from the next version, requiring a previous version to compile.

16:14 Licenser_: makes sense

16:14 I like clojure, I really like it i must say =)

16:16 hiredman: I was kind if thinking, you could do a stripped down sort of stage one lisp, where the reading and compiler used java.util.* datastructures and then bootstrap clojure with that

16:16 Chousuke: or the java bits could be kept in, but moved out of the main namespace into clojure.bootstrap or something.

16:17 But I think first we need the actual c-in-c compiler :P

16:18 Licenser_: heh

16:18 yes that might be tricky

16:19 Chousuke: I should just get my reader to a state where I can introduce it to people ;(

16:20 still missing unicode escapes...

16:20 danlei: Chousuke: where is it?

16:20 hiredman: the whole bootstrapping thing makes my head spin when I try to think about it

16:21 Chousuke: also eval'ing clojure.core hit a roadblock with ns. apparently you can't redef "ns" in any namespace.

16:21 hiredman: clojure needs to have it's datastructures availble for clojure code to be read, but if the datastructures are written in clojure…

16:21 Chousuke: hiredman: heh.

16:21 hiredman: *brain hurt*

16:22 danlei: Chousuke: you have the source of your reader online?

16:22 Chousuke: hiredman: that's why you use an earlier compiler to compile the data structures first, and then recompile with the resulting compiler :P

16:22 danlei: yeah. http://www2.sandbox.google.com/search?q=clojure-reader

16:23 oops

16:23 wrong url.

16:23 http://github.com/Chousuke/clojure/commits/clojure-reader

16:23 danlei: Chousuke: thanks

16:23 Chousuke: not documented, optimised or organised in any way :P

16:24 danlei: that's ok, I'm just interested and wanted to take a look

16:26 Chousuke: I guess I should put some helper function in there to produce the reader input data structure from a string, for people who want to play with it.

16:26 danlei: github is slow as hell for me atm :|

16:30 Chousuke: danlei: I pushed a helper function in there. should make it easier to play with.

16:32 LauJensen: danlei: Guess why people are moving to Gitorious

16:33 Chousuke: The Github people did blog about the slowness some time ago, didn't they?

16:33 apparently they're working on it :/

16:33 technomancy: we should at least have an auto-updating mirror on gitorious for the downtime/slowtime

16:33 LauJensen: I mailed them about it Chousuke, says they've been working on a fix since april, expect something big to happen "soon"

16:38 danlei: Chousuke: thanks

16:45 technomancy: I'll set up auto-pushes later: http://gitorious.org/clojure/clojure/trees/master

16:45 for now it has master, 1.0.x, and new branches

16:52 danlei: hm, there was some feature like CL's * ** *** (result of last evaluations) in clojure, wasn't it?

16:53 Chouser: *1 *2

16:53 danlei: aaah, thanks

16:54 Chousuke: technomancy: why don't you just push all the branches as they are from github to gitorious? :/

16:55 technomancy: Chousuke: only because I just haven't got a chance to look into automating it yet

16:56 ankou: hi is there a function which checks if an item is contained in a list?

16:57 hiredman: ,(.contains '(1 2 3) 2)

16:57 clojurebot: true

16:57 hiredman: ,((set '(1 2 3)) 2)

16:57 clojurebot: 2

16:57 hiredman: ,((set '(1 2 3)) 4)

16:57 clojurebot: nil

16:57 hiredman: ~def set

17:00 hmmm

17:00 danlei: Chousuke: after a first glance, I find it really nice :)

17:01 Chousuke: danlei: I tried to keep it that way. If it hadn't been fun to write I don't think I would've gotten this far :P

17:01 danlei: Chousuke: but I see you hardcoded the dispatch table, is that subject to change; will you expose the table to allow prefix-dispatch chars definition by the users?

17:02 Chouser: danlei: not if he wants rhickey to accept it

17:03 danlei: I mean, it's all there :) just add a char and define a method on a char

17:03 Chouser: I see

17:03 but it'd be trivial to do so

17:03 Chousuke: yeah, it would.

17:03 danlei: I understand rich's sentiments

17:03 reader macros tend to be ugly

17:04 Chouser: yes. also pretty simple to open up clojure's current reader to user defined reader macros

17:04 danlei: and clojure already has a lot of handy reader extensions

17:04 Chousuke: I just decided to emulate clojure behaviour for now.

17:04 Chouser: but once its available to users, it would be very hard to change or take away

17:04 danlei: anyway, nice piece of work, as far as I can tell (not trivial, just my first impression)

17:05 Chouser: yes, that's right

17:05 Chousuke: I won't be too disappointed if that reader ends up getting rewritten though.

17:06 it's still got many pieces that should be useful in any clojure reader implementation.

17:06 danlei: sure, I'll dive in a bit more, when I've got the time to do so

17:06 ankou: okay and is there another (maybe faster) way to check if there is any element in a list which satisfied a given predicate then just checking the size of the result of filter?

17:07 technomancy: (doc any?)

17:07 clojurebot: Titim gan éirí ort.

17:07 technomancy: ,(doc any?)

17:07 clojurebot: Titim gan éirí ort.

17:07 technomancy: ... =(

17:07 hiredman: ,(doc some)

17:07 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

17:08 Chousuke: danlei: just be aware that it's still missing some bits. like unicode escapes :P

17:08 danlei: Chousuke: not a problem.

17:09 Chousuke: and #! and #_... hmm.

17:09 those ought to be trivial to implement though

17:09 danlei: well, #_ shouldn't be hard, what's #! again?

17:09 Chousuke: it's basically a comment too.

17:09 Chouser: #!/bin/clojure

17:09 danlei: ah, ok

17:09 for scripting, I see

17:10 Chousuke: they're so easy I just haven't bothered writing support for them :D

17:10 * hiredman sort of feels motivated to work on his reader again

17:10 danlei: :)

17:10 hiredman: but I don't have a ca in

17:12 Chouser: hiredman: is that on purpose?

17:12 hiredman: no, I just hate mailing stuff

17:12 danlei: you're not alone :)

17:15 hiredman: I think I have the ca sitting on my desk at home (I definitely did before I cleaned up last weekend)

17:26 Chousuke: hmm.

17:26 now there is support for #! and #_ (though #_ probably could be smarter)

17:26 as it is, #_ actually reads the following form and then drops it...

17:28 danlei: yes, I see, creates an anonymous function without a body and calls it

17:29 hiredman: eh?

17:29 Chousuke: it does have a body, I used the function to avoid holding on to the old rh when consuming the ignored form

17:30 ... though that may not help as my other consume methods are not as careful :)

17:30 but I intend to fix that.

17:32 ,#_#=(clojure.core/println "foo")

17:32 clojurebot: EOF while reading

17:32 Chousuke: hm

17:32 ,#_#=(clojure.core/println "foo")'a

17:32 clojurebot: a

17:32 foo

17:40 danlei: ah, misread that

17:47 ankou: the documentation talks about the read table as an extension system, so how can I access the read table?

17:48 hiredman: uh, what?

17:48 which docs?

17:48 Chousuke: ankou: the read table is not accessible to users.

17:48 hiredman: rhickey specificly does not allow access to the read table

17:49 ankou: The behavior of the reader is driven by a combination of built-in constructs and an extension system called the read table.

17:49 Chousuke: yeah, but that extension system is only modifiable by the implementors.

17:50 it's that way because no-one has yet come up with an acceptable solution for conflicting reader macros.

17:51 hiredman: ankou: there are many threads on the google group that discuss this

17:51 ankou: okay

17:52 is it possible to include clojure as a library in any java program to use clojure as a scripting language for that program?

17:52 hiredman: sure

17:53 I don't think there are any frame works to do it, but it should be relatively simple to setup

17:54 you just initialize the clojure runtime, and fire it up

17:55 ankou: is there any documentation how to do that from java?

17:57 hiredman: http://en.wikibooks.org/wiki/Clojure_Programming/Tutorials_and_Tips#Invoking_Clojure_from_Java

17:58 ankou: great, thanks

18:29 danlei: how can I access a non-public var from another namespace?

18:30 hiredman: :/

18:30 danlei: not at all?

18:30 hiredman: there are ways

18:31 danlei: for example?

18:31 hiredman: I forget

18:31 danlei: ok, but nothing like foo::bar I guess?

18:31 hiredman: some kind of mix of various reader macros

18:31 danlei: ok, ty

18:31 cemerick: #'other.namespace/foo will get you the var, regardless of its :public metadata

18:32 hiredman: #'clojure.core/throw-if

18:32 ,#'clojure.core/throw-if

18:32 clojurebot: #'clojure.core/throw-if

18:32 hiredman: ,@#'clojure.core/throw-if

18:32 clojurebot: #<core$throw_if__5764 clojure.core$throw_if__5764@16909e0>

18:33 danlei: thanks!

23:20 JAS415: I have a question about mapping

23:20 hiredman: the map function?

23:20 JAS415: it seems that whenever I do a map operation rather than just evaluating the head of the sequence, it will evaluate an arbitrary number off of the head

23:20 yeah

23:21 hiredman: uh

23:21 JAS415: so i'm doing mapcat on a function that does an api request to get a lazy seq of requests

23:21 hiredman: ah

23:21 so you are not mapping

23:21 you are mapcatting

23:21 JAS415: it'll do 4 requests, i want 1

23:21 right but i would have expected that to be the same thing

23:21 hiredman: mapcat uses concat, and concat is not fully lazy

23:22 JAS415: oooh

23:22 i didn't realize concat wasn't fully lazy

23:22 that could be the root of many of my problems

23:22 hiredman: ,(doc concat)

23:22 clojurebot: "([] [x] [x y] [x y & zs]); Returns a lazy seq representing the concatenation of the elements in the supplied colls."

23:22 hiredman: ,(doc lazy-cat)

23:22 clojurebot: "([& colls]); Expands to code which yields a lazy sequence of the concatenation of the supplied colls. Each coll expr is not evaluated until it is needed. (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))"

23:23 hiredman: lazy-cat is a macro though

23:23 JAS415: yeah i couldn't use it with an arbitrary number i suppose

23:26 yeah switching to a straight map fixes it

23:27 i'll just rearrange my code to accomodate that

23:27 thanks!

23:29 tomoj: is concat partially lazy? what does that mean?

23:29 JAS415: well it seems to be chunked or something

23:29 like

23:29 do

23:30 (apply concat (map fn seq))

23:30 cark: i think tha has to do with the multiple parameter lists

23:30 JAS415: it'll evaluate the first few of the seq from resulting map

23:30 cark: though you would see 3 elements realized instead of 4

23:52 technomancy: the mirror at http://gitorious.org/clojure/clojure should be fully automated now

23:52 clojurebot: gitorious mirror is http://gitorious.org/clojure/clojure

23:52 clojurebot: In Ordnung

23:53 technomancy: for github's slow days

Logging service provided by n01se.net