#clojure log - Mar 31 2009

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

0:17 Jedi_Stannis: what's the difference between while and when in list comprehnsions?

0:17 gnuvince_: Jedi_Stannis: while stops when the condition becomes false

0:17 hiredman: while is like take-while

0:17 gnuvince_: ,(for [x [1 3 5 6 7 9] :while (odd? x)] x)

0:17 clojurebot: (1 3 5)

0:17 gnuvince_: ,(for [x [1 3 5 6 7 9] :when (odd? x)] x)

0:17 clojurebot: (1 3 5 7 9)

0:17 hiredman: when is like filter

0:17 Jedi_Stannis: got it, thanks

0:17 yeah

0:17 tried a simple example where they were the same at first, and wasn't sure what the difference was

0:21 gnuvince_: -Xprof reports that 20% of my program is spent in java.lang.reflect.Array.set; I have a type hint for that array, is there anything else I need to do to avoid reflection?

0:27 slashus2: gnuvince_: Any luck on performance increases?

0:29 erohtar: is there a way to get the name of a function from its object representation?

0:29 say - get "println" if you're given println

0:29 hiredman: nope

0:30 well

0:30 yes, but it would involve a lot of work

0:31 Fns have no names, no names man, they are nameless

0:32 erohtar: ok - makes sense

0:32 what is the type of the params when they're sent into a macro?

0:32 are they symbols?

0:32 gnuvince_: slashus2: yes

0:32 slashus2: I cut performance down from 2 minutes 40 seconds to a little under 2 minutes on my home machine.

0:32 hiredman: erohtar: depends

0:32 gnuvince_: slashus2: I completely changed the way parsing was done (the outside interface remains the same however)

0:32 erohtar: (defmacro macro-name [param1] ())

0:32 gnuvince_: It's now shorter and faster, but I have this weird reflection call that I can't put my finger on.

0:32 erohtar: what would param1 be?

0:33 dnolen: it depends on what you call the macro with

0:33 hiredman: param1 is whatever macro-name was called on

0:33 dnolen: it would be an unevaluated something.

0:33 erohtar: what would its type be?

0:33 hiredman: param1 is whatever macro-name was called on

0:36 dnolen: ,(defmacro return-types [& args ] `(list ~@(map type args)))

0:36 clojurebot: DENIED

0:36 dnolen: bleh anyways try that erohtar

0:36 and this

0:36 (macroexpand-1'(return-types asym [1 2 3] {:key :val}))

0:37 erohtar: got it - its Symbol

0:37 thanks

0:37 hiredman: forget types, while useful they are not helping you here

0:37 if what is passed to the macro is a symbol it is a symbol

0:37 if it is not a symbol it is not a symbol

0:38 macros can take any form the reader can produce

0:38 clojurebot: Holy Crap.

0:38 hiredman: clojurebot: crazy, I know

0:39 clojurebot: Pardon?

0:40 hiredman: .(:macro (meta delay))

0:40 ,(:macro (meta delay))

0:40 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/delay

0:40 hiredman: ,(:macro (meta (var delay)))

0:40 clojurebot: true

0:40 hiredman: ,(delay 1)

0:40 clojurebot: #<Delay@1daed02: 1>

0:40 hiredman: ,(class 1)

0:40 clojurebot: java.lang.Integer

0:41 hiredman: ,(delay '(1 2 3))

0:41 clojurebot: #<Delay@68d91: (1 2 3)>

0:41 hiredman: ,(class '(1 2 3))

0:41 clojurebot: clojure.lang.PersistentList

0:52 danlarkin: how should I determine whether or not I need to deref something, is (instance? clojure.lang.IDeref foo) the best way?

0:55 hiredman: sounds good

0:55 erohtar: How would i get the first thing passed into defmacro as a keyword?

0:56 hiredman: depends

0:56 erohtar: im trying to write a macro that looks like defn, but registers the function in a map also

0:56 for that, i need the name of the fn being defined as a keyword

0:56 hiredman: why?

0:56 dnolen: erohtar you can use anything as a key in a map.

0:56 ,{'a 1 'b 2}

0:56 clojurebot: {a 1, b 2}

0:56 dnolen: including symbols.

0:56 erohtar: yes, but i want to use the name of the fn as a key

0:56 hiredman: ...

0:56 cmvkk: ,(keyword (str 'a))

0:56 hiredman: fns don't have names

0:56 clojurebot: :a

0:56 erohtar: yes, but since im trying to create something like a defn, i have the "name"

0:56 cmvkk: right, and that name is a symbol.

0:56 you can then use the symbol as the key in a map.

0:56 dnolen: ,{'a (fn [])}

0:56 clojurebot: {a #<sandbox$eval__4919$fn__4921 sandbox$eval__4919$fn__4921@96bfda>}

0:56 erohtar: inside the macro, it doesnt seem to work

0:56 cmvkk: are you trying to register it in a map from inside the macro?

0:56 because that's probably a bad idea...

0:56 hiredman: because you are doing it wrong

0:56 pastbin

0:56 lisppaste8: url?

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

0:56 erohtar: yes... im trying to register it from inside the macro

0:56 cant be done?

0:56 cmvkk: what you need is like (defmacro foo [name & body] `(do (defn ~name ~@body) (register ~name)))

0:56 that way, the registering is code that occurs in the expansion

0:58 lisppaste8: erohtar pasted "untitled" at http://paste.lisp.org/display/77802

0:59 danlarkin: erohtar: would looking at the ns-publics of the namespace in which you declare the function maybe make more sense?

0:59 cmvkk: erohtar, you should probably use syntax-quote, it makes macros a lot easier to read

0:59 just as an aside

0:59 erohtar: yes - this is my first real macro writing experience

0:59 hiredman: erohtar: are you the guy with the database thing?

0:59 erohtar: yes

0:59 hiredman: if so, don't bother with defn or a macro

1:00 cmvkk: erohtar, if you want to fix that macro though, your problem is that you're defining the function after you try and put its value into the map

1:00 hiredman: just create a fn and stick it in th map

1:01 erohtar: i tried to defn the function first, because else it wasnt able to evaluate the name

1:01 hiredman: ,(assoc {} :f (fn [x] x))

1:01 clojurebot: {:f #<sandbox$eval__4925$fn__4927 sandbox$eval__4925$fn__4927@1c2862b>}

1:01 erohtar: hiredman: yes, i can do that

1:01 ah -

1:01 just using the : will work it?

1:01 see thats what i need

1:03 hiredman: no

1:03 no

1:03 erohtar: then?

1:03 hiredman: stop

1:03 dnolen: ,(assoc {} 'f (fn [x] x))

1:03 clojurebot: {f #<sandbox$eval__4931$fn__4933 sandbox$eval__4931$fn__4933@14708f5>}

1:03 dnolen: ,(assoc {} '+ (fn [x] x))

1:03 hiredman: ,(assoc {} 1 (fn [x] x))

1:03 clojurebot: {+ #<sandbox$eval__4937$fn__4939 sandbox$eval__4937$fn__4939@aa3e6e>}

1:03 {1 #<sandbox$eval__4943$fn__4945 sandbox$eval__4943$fn__4945@6f2c06>}

1:03 dnolen: ,(assoc {} [1 2 3] (fn [x] x))

1:03 clojurebot: {[1 2 3] #<sandbox$eval__4949$fn__4951 sandbox$eval__4949$fn__4951@1fb5664>}

1:03 dnolen: erohtar they all work.

1:03 hiredman: anything can be a key in a map

1:04 erohtar: i know that part - but i want the "name" of the function to be the key

1:04 dnolen: we've demonstrated that you can do that.

1:04 hiredman: no, you don't

1:04 you may, but you are mistaken

1:04 erohtar: why do u say that - here's what i wanna do with this

1:04 hiredman: because functions don'

1:04 t have names

1:04 erohtar: agreed -

1:04 hiredman: so, you cannot have the name of a function as a key, becaue names of functions don't exist

1:04 erohtar: but since this particular fn is being defined using a macro which accepts the name also .... there is a logical name i want to use

1:04 in the pastie, service-name is that name

1:04 hiredman: it does not accept a name

1:04 erohtar: http://paste.lisp.org/display/77802

1:04 hiredman: there is no such thing as a name

1:05 there are symbols

1:05 erohtar: there, defsevak is the macro - which accepts service-name

1:05 oh

1:06 hiredman: I really recommend you persue a non-macro approach until later

1:06 slashus2: erohtar: It may be easier if you use a syntax quote.

1:06 erohtar: heh

1:06 ok

1:06 lemme read abt macros a bit more :)

1:06 hiredman: get it working with functions

1:06 erohtar: yup

1:07 hiredman: a macro is just to make it looki pretty

1:07 erohtar: fair enuff, thanks

1:07 sudoer: can i use clojure for web 2.0?

1:07 danlarkin: sudoer: no

1:07 slashus2: :-|

1:08 hiredman: clojure only works with web 3.0 and above

1:08 danlarkin: ok so I'm confused here:

1:08 (binding [outer 1] (future (binding [inner outer] inner)))

1:08 dnolen: sudoer: you should look at compojure, it's still early but clojure could be good for the web soon.

1:08 danlarkin: that gives, java.lang.IllegalStateException: Var user/outer is unbound.

1:08 clojurebot: ?

1:08 sudoer: dnolen: yes, I am looking into that

1:09 slashus2: danlarkin: Doesn't binding work with existing vars?

1:09 hiredman: correct

1:09 danlarkin: slashus2: yes -- both outer and inner have been def'ed

1:09 slashus2: okay

1:10 hiredman: danlarkin: you need to make a thunk of the binding then run the thunk in the future

1:11 slashus2: danlarkin: It worked for me.

1:11 danlarkin: slashus2: it did? Hm, time to svn up clojure

1:12 slashus2: ,(let [*outer* 0 *inner* 0] (binding [*outer* 1] (future (binding [*inner* *outer*] *inner*))))

1:12 clojurebot: java.lang.Exception: Unable to resolve var: *outer* in this context

1:12 slashus2: that won't work

1:12 sorry

1:12 You have to use def

1:12 Don't know why I would have expected that to work.

1:14 hiredman: user=> (binding [outer 1] (future (binding [inner outer] inner)))

1:14 java.lang.IllegalStateException: Var user/outer is unbound.

1:15 danlarkin: hiredman: ((deref (binding [outer 1] (future #(binding [inner outer] inner))))) gives the same error

1:15 hiredman: it would

1:15 danlarkin: did I not thunk the binding?

1:15 slashus2: (def *outer* 0) (def *inner* 0) (binding [*outer* 1] (future (binding [*inner* *outer*] *inner*))) is the code that I am using

1:16 hiredman: slashus2: #<Object$Future$IDeref@c623af: 0>

1:16 slashus2: yup

1:16 Is that not what he is trying to do?

1:17 danlarkin: it should be 1

1:17 slashus2: oh

1:17 :-(

1:17 interesting

1:18 hiredman: user=> (binding [outer 1] (let [f outer] (future (binding [inner f] inner))))

1:18 #<Object$Future$IDeref@33f0de: 1>

1:20 dynamic scope is not closed over by the fn object future makes

1:20 slashus2: So you have to make a local scope..

1:20 clojurebot: scope is at http://paste.lisp.org/display/73838

1:20 slashus2: wow

1:20 hiredman: lexical scopre :P

1:20 slashus2: static scope

1:21 danlarkin: hiredman: excellent. thanks again

1:23 hiredman: good to know

1:23 I should make sure to remember this

1:26 slashus2: hiredman: Put it in clojurebot

1:27 hiredman: clojurebot: fn?

1:27 clojurebot: It's greek to me.

1:28 lisppaste8: erohtar annotated #77802 "working now" at http://paste.lisp.org/display/77802#1

1:29 hiredman: clojurebot: future is <reply>#who: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff

1:29 clojurebot: Roger.

1:29 erohtar: that seems to work as expect, thanks hiredman

1:29 hiredman: clojurebot: why doesn't future work?

1:29 clojurebot: why not?

1:29 hiredman: $%#@%

1:30 ~how come future doesn't work?

1:33 clojurebot: hiredman: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff

1:33 dnolen: hiredman: that's seem like a very interesting case you found, perhaps enough to post on the mailing list?

1:33 ,(binding [*outer* 1] (let [*outer* *outer*] (future (binding [*inner* *outer*] *inner*))))

1:33 clojurebot: java.lang.Exception: Unable to resolve var: *outer* in this context

1:33 hiredman: I dunno that it is actually that interesting

1:33 dnolen: the above works so it seems like the binding expression should create the scope so that future calls work as expected right?

1:33 hiredman: no

1:33 binding should most defintely create a lexical scope

1:33 er

1:33 not

1:33 binding should most defintely not create a lexical scope

1:33 dnolen: in which case would providing a new binding not provide it in the current scope?

1:33 clojurebot: new Class(x) is (Class. x)

1:33 hiredman: no

1:33 binding is dynamic scope

1:33 let is leixcal scope

1:33 dnolen: ahh

1:33 gotcha, just checked

1:33 it's default behavior

1:33 learn something new everyday.

1:33 hiredman: lexical scope is, uh, capturedwhen a fn is created

1:34 dynamic scope when it is executed

1:36 slashus2: ((binding [*outer* 1] (fn [] (println *outer*))))

1:36 I understand

1:37 dnolen: ,(binding [*outer* 5] (println *outer*) ((fn [] (println *outer*))))

1:37 clojurebot: java.lang.Exception: Unable to resolve var: *outer* in this context

1:37 dnolen: ,(def *outer* 0)

1:37 clojurebot: DENIED

1:37 dnolen: ,(let [*outer* 0] (binding [*outer* 5] (println *outer*) ((fn [] (println *outer*)))))

1:37 clojurebot: java.lang.Exception: Unable to resolve var: *outer* in this context

1:38 slashus2: dnolen: That doesn't create a dynamic var.

1:39 dnolen: ,(binding [outer 5] (println outer) ((fn [] (println outer))))

1:39 clojurebot: java.lang.Exception: Unable to resolve var: outer in this context

1:39 * hiredman waives his hands about

1:39 dnolen: haha

1:39 hiredman: ,*outer*

1:39 clojurebot: 1

1:40 dnolen: ,(binding [*outer* 5] (println *outer*) ((fn [] (println *outer*))))

1:40 clojurebot: 5 5

1:40 dnolen: why that?

1:40 cmvkk: ,((let [*foo* 2] (with-local-vars [*foo* 3] (do (print *foo*) (fn [] (print *foo*)))))

1:40 clojurebot: EOF while reading

1:40 cmvkk: crap!

1:40 dnolen: why 5 5 if no lexical scope?

1:40 ah because println is an fn call?

1:40 hiredman: you are executing the fn in the dynamic scope

1:40 dnolen: er not ah

1:41 light goes off

1:41 cmvkk: ,((let [*foo* 2] (with-local-vars [*foo* 3] (do (print @*foo*) (fn [] (print @*foo*))))))

1:41 clojurebot: java.lang.IllegalStateException: Var null/null is unbound.

1:41 dnolen: because the var when returned has it binding popped off!

1:41 cmvkk: oh well.

1:41 yes.

1:42 ,(let [*foo* 2] ((with-local-vars [*foo* 3] (do (print @*foo*) (fn [] (print @*foo*))))))

1:42 clojurebot: java.lang.IllegalStateException: Var null/null is unbound.

1:42 hiredman: ,((binding [*outer* 5] (println *outer*) (fn [] (println *outer*))))

1:42 dnolen: coolz

1:42 clojurebot: 5 1

1:43 dnolen: gotcha, so future makes sense, the binding has already been removed by the time future execs

1:44 slashus2: ,((binding [*outer* 1] (fn [] (println *outer*))))

1:44 clojurebot: 1

1:44 slashus2: ((binding [*outer* 2] (fn [] (println *outer*))))

1:44 okay

1:44 ,((binding [*outer* 2] (fn [] (println *outer*))))

1:44 clojurebot: 1

1:47 danlarkin: Hm... why in the world do I get a minute long 0.1 cpu usage sleep by java at the end of running this script with futures...

1:48 hiredman: always?

1:48 danlarkin: yep

1:48 the deref is successful so it's not like it's blocking there

1:48 hiredman: GC? threadpool spin down? dunno

1:52 danlarkin: Hmmmm yeah I donno either

1:56 hiredman: ~latest

1:56 clojurebot: latest is 1337

1:56 replaca: wow, that's leet! :)

1:57 cmvkk: that's been the latest for a few days hasn't it

1:57 hiredman: yeah

1:57 replaca: official script kiddie version

1:57 hiredman: I was just thinking that

1:57 1.0 is 1337

1:57 :P

1:57 replaca: it will be

1:57 cmvkk: it's not 1.0 is it?

1:57 replaca: things are feeling good lately

1:57 no, not really

1:58 hiredman: sounds like rich has gone into deep meditation about hierarchies

1:58 cmvkk: i assume, since the last release was just another dated release, that he just gave up on numbered releases entirely.

1:59 replaca: hmm, I think he's still going towards 1.0, but he wants to get some of these issues stabilized first

2:00 to reduce breaking changes later

2:00 hiredman: ^-

2:00 he wants to run free as the wind

2:00 which after promising to not make breaking changes will be hard

2:00 danlarkin: JSwat calls the main thread "zombied" when it's just sitting there waiting after all the work is done

2:00 hiredman: maybe all the futures are not done yet?

2:01 dnolen: hiredman: true, but if the hierarchies problem can be solved i think the fundamentals of Clojure will be quite solid.

2:01 hiredman: the main thread finishes but stuff is still runing on the threadpools

2:01 ?

2:01 Jedi_Stannis: what's the current issue with hierarchies?

2:01 dnolen: it's the only thing I find troubling really about Clojure, is that it's hard to model the more useful aspects of OO and inheritance.

2:02 hiredman: dnolen: I have yet to care about hierarchies, so clojure is already sollid for me

2:02 dnolen: hiredman: understandable, but because you don't need to model them. Other people clearly do.

2:02 hiredman: but I hav ebeen following as much as I can of that thread

2:03 dnolen: Jedi_Stannis: it's very difficult to handle to multiple inheritance in any way where ordering the relationships is important.

2:06 Jedi_Stannis: there's a lot of hoop-jumping to model the idea of super or even interfaces in pure Clojure as well.

2:06 Jedi_Stannis: I see

2:06 dnolen: Jedi_Stannis: it's tough, multimethods are already really really useful and elegant. ad-hoc hierarchies as well.

2:07 personally i'm against deep hierarchies, but being unable to implement super/next-method easily, and controlling execution order of multiple parents really decreases code reuse and extensibility.

2:09 if Rich can solve it, I think he's as close as anyone gotten to unifying a the particle (SmallTalk) and field (Lisp) models of OO.

2:10 Jedi_Stannis: yeah, rich seems like a pretty good designer, we'll see what he comes up with

2:11 replaca: dnolen: what do you think about before and after methods?

2:16 dnolen: replaca: i think they're really, really cool, but I don't miss them too much. Mostly a convenience, and something if where I really needed them, I wouldn't be bothered by reinventing the wheel.

2:17 replaca: dnolen: as long as we could. But yes, I've always liked them more than I used them :-)

2:22 dnolen: one problem I see, as has been pointed out somewhat by mikel, is that next-method really requires introspection, and there's no obvious place to put this info. not all objects take metadata for example. multimethods nicely work with everything.

2:22 replaca: yeah, makes sense

2:22 I haven't been thinking about it as hard as you guys

2:31 fffej: I'm trying to do some file parsing - is there something like read-string that'll read all the lisp forms of one line?

5:48 MikeSeth: are chats here logged?

5:52 Holcxjo: http://clojure-log.n01se.net/date/

10:19 antifuchs: how can I create an array of floats? I don't need java.lang.Floats, but floats

10:21 Cark: ,(doc make-array)

10:21 clojurebot: "([type len] [type dim & more-dims]); Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

10:21 antifuchs: ah. thanks!

10:21 Cark: ,(make-array Float/TYPE 10)

10:21 clojurebot: #<float[] [F@71a3e>

10:21 antifuchs: this doesn't really work with into-array, right?

10:22 Cark: hum

10:22 AWizzArd: ,(doc into-array)

10:22 clojurebot: "([aseq] [type aseq]); Returns an array with components set to the values in aseq. The array's component type is type if provided, or the type of the first value in aseq if present, or Object. All values in aseq must be compatible with the component type. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

10:22 Cark: ,(into-array float/TYPE '(0.1 0.2 0.3))

10:22 clojurebot: java.lang.Exception: No such namespace: float

10:22 Cark: ,(into-array Float/TYPE '(0.1 0.2 0.3))

10:22 clojurebot: java.lang.IllegalArgumentException: argument type mismatch

10:22 AWizzArd: ,(into-array [1 2 3] Integer/TYPE)

10:22 clojurebot: java.lang.ClassCastException: clojure.lang.LazilyPersistentVector cannot be cast to java.lang.Class

10:22 AWizzArd: hmm

10:22 Cark: ,(into-array Float/TYPE (map float [0.1 0.2 0.3]))

10:22 clojurebot: #<float[] [F@4d2b18>

10:22 Cark: ,(into-array Float/TYPE [0.1 0.2 0.3])

10:22 clojurebot: java.lang.IllegalArgumentException: argument type mismatch

10:22 Cark: (class 0.1)

10:22 ,(class 0.1)

10:22 clojurebot: java.lang.Double

10:22 rsynnott: does 'float' in this context specifically mean 32bit float?

10:22 Cark: ,(class (float 0.1))

10:22 clojurebot: java.lang.Float

10:22 Cark: ,(into-array Double/TYPE [0.1 0.2 0.3])

10:22 clojurebot: #<double[] [D@94ef06>

10:22 Cark: tadah

10:22 AWizzArd: ,(into-array Integer/TYPE [10 20 30])

10:22 clojurebot: #<int[] [I@6d74aa>

10:22 AWizzArd: ,(vec (into-array Integer/TYPE [10 20 30]))

10:22 clojurebot: [10 20 30]

10:22 AWizzArd: rsynnott: yes

10:22 Cark: so double is 64bit in java ?

10:22 rsynnott: hmm, you're not really meant to use those in general, anyway, are you?

10:22 AWizzArd: ,(class (into-array Float/TYPE (map float [0.1 0.2 0.3])))

10:22 clojurebot: [F

10:22 AWizzArd: rsynnott: why not?

10:23 It is made easy to create arrays in Clojure.

10:23 rsynnott: AWizzArd: doubles are faster on modern machines, usually

10:23 AWizzArd: ah okay, I thought you meant Clojure vectors vs Arrays

10:23 rsynnott: nope

10:24 Cark: you'll want to use these for java interop, so i guess it depends on what is expected

10:24 rsynnott: (in particular, last I heard they were MUCH faster on modern x86s, due to the use of SSE for most FP stuff)

10:24 Cark: you mean in general or with java ?

10:24 as in : do we know if java uses SSE ?

10:25 AWizzArd: ~google java sse

10:25 clojurebot: First, out of 80700 results is:

10:25 Java 2 Platform, Standard Edition (J2SE Platform), version 1.4.2

10:25 http://java.sun.com/j2se/1.4.2/1.4.2_whitepaper.html

10:25 rsynnott: Cark: I'm not sure if it does

10:25 Cark: looks like it does =P

10:26 rsynnott: (but doubles should be faster on modern x87 anyway)

10:31 Cark: i think i neve professionaly used float or doubles ...

10:31 never*

10:31 mhh actually i did with gdi+ !

10:33 cemerick: rsynnott: I heard the same thing from the horse's mouth, as it were, @ ILC last week. A fellow who apparently worked on some float machinery in javac told me that doubles should always be faster, except perhaps on Power architectures.

10:34 I plan on doing some benchmarking with our libraries on that issue, as they use floats *everywhere*.

10:38 AWizzArd: cemerick: Do you write tests in Enclojure for your Clojure code?

10:42 cemerick: AWizzArd: we write tests in clojure, and happen to use enclojure, yes

10:42 that is, enclojure has little to do with the tests we write

10:42 AWizzArd: Do you use contrib test-is?

10:44 cemerick: yes, please. :-)

10:45 AWizzArd: I asked specifically for Enclojure, because that means you are doing it in NetBeans. In NB I saw that they have this Test Libraries and Test Packages thing. Do you also use those?

10:45 cemerick: isn't that just an NB library that contains junit?

10:45 oh, nm, I understand what you're referring to

10:45 Raynes: Why is it that only Enclojure provides a decent way to automatically build executable jars with Clojure? :|

10:45 cemerick: that's just a way to configure your build so that your test files aren't copied into your distribution jar

10:45 Raynes: does it? We've always just rolled our own clojure build process, mostly because we're picky. :-)

10:45 rsynnott: Raynes: probably people don't see it as a priority to automate

10:45 it's not as if it's something that most people have to do terribly frequently

10:45 AWizzArd: What I have is a repository that contains (or will contain in the future) many NB project folders. Cool would be: start one script that builds all these projects. And then it should also automatically test them all. (the jars won't contain the tests). Is that possible?

10:47 Raynes: La Clojure is kinda nice.

11:11 cemerick: AWizzArd: what you want is a proper build/test process for each project (which can be factored out into a single ant build file and included by all other projects) + a good CI environment like hudson

11:28 AWizzArd: did you say you were building forms in matisse and then providing a method on the form that returns a list of all of the widgets in the form?

11:41 AWizzArd: Only some of the projects will offer GUIs. But yes, in the Matisse code I have one getWidgets method which I call from Clojure, where I then do all the work. (like setting up event handlers)

11:44 cemerick: btw, what is a "CI environment"?

11:45 cemerick: AWizzArd: I mention it only because you can simply set the access level of the widgets in the form to public final (for example) instead of private. That would remove the necessity of maintaining the getWidgets method, and allow simple access via (.myWidgetName form), etc.

11:45 CI == continuous integration

11:45 p_l: cemerick: start the app by typing (myappname) in REPL. Write code to fix errors that got thrown, type again, go back to writing code ;-)

11:45 cemerick: heh

11:47 AWizzArd: cemerick: yes, I also sometimes did that and I keep this option (setting the field public) for the future. Anyway, about the tests. So I would add "Test Packages" and do the tests there, with clojure.contrib (for example). And later, when I have 2+ projects I will have to write one Ant file which can build all projects and then run the tests?

11:47 cemerick: AWizzArd: You want each project to be buildable and testable on its own. All that really requires is (a) having tests written in some form (junit|test-is|other), and (b) a build process that can produce the distributable code and then invoke the tests within a context that includes the distributable code on the classpath.

11:47 AWizzArd: yes

11:47 cemerick: finally dug myself out from under my mailing list backlog :-)

11:47 I really can't understand the interest in talking about coding conventions in the Java side of clojure.

11:47 rhickey: cemerick: me neither

11:47 * cemerick restrains himself from cracking (not so) wise... :-P

11:47 cooldude127: lol

11:47 rhickey: I fully admit it's not idiomatic, OTOH, I'm quite proud of the class hierarchy - it was nice to present it coherently at ILC

11:49 cooldude127: what's wrong with the clojure java code?

11:49 cemerick: rhickey: I'm glad you're thinking about precedence and such. Learning some more about MOP @ ILC made me think of some cases where it makes sense to apply multiple methods to a particular value. Streamlining that kind of stuff would be very, very nice.

11:49 "for a particular dispatch value", I mean

11:49 cooldude127: some don't like the formatting and such.

11:49 I don't really, either, but I'd really rather rhickey spent his time and attention on things of significance.

11:49 rhickey: slides with factored class diagrams: http://clojure.googlegroups.com/web/tutorial.pdf

11:50 cemerick: yeah, I just wish people could think outside the CLOS box a bit - a la carte hierarchies have a lot of advantages

12:07 cemerick: rhickey: yeah, those are really helpful...I ended up grokking some things that were very fuzzy before

12:09 rhickey: my big use case right now is in rendering code that uses multimethods -- I often want to have all of a dispatch value's ancestor methods invoked for the method's arguments before the 'narrowest' match is invoked.

12:09 clojurebot: he works hard so you don't have to

12:09 cemerick: hiredman: damn, that one worked out well! :-D

12:09 cmvkk: can't you do that manually?

12:09 cemerick: well, yeah, and I do right now. It's a lot more fragile than call-next-method or super.foo(blah...), though.

12:09 that's a price worth paying for the a la carte factor, tho.

12:09 rhickey: call-next-method has inherent problem IMO, convenient as it may seem

12:09 cemerick: yeah, they all do, probably more than I know of given my purely "userland" experience

12:09 rhickey: I can make it easier, e.g.: (apply (get-method ameth asuper) args), but you'll have to supply the super explicitly

12:11 cemerick: danlarkin: future uses the clojure.lang.Agent/soloExecutor thread pool, which uses a 'cached thread pool' from the Executors framework

12:15 from the Executors.cachedThreadPool() javadoc: If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache.

12:15 danlarkin: Hm!

12:15 cemerick: ThreadPoolExecutor (the concrete class behind cachedThreadPool) is parameterized in the timeout that it uses, so fixing this is fundamentally trivial.

12:15 however, right now, the future fn is tied to the current soloExecutor, and how and whether that should be changed (or parameterized so that you can control which thread pools some futures go to?) is above my pay grade.

12:15 paging rhickey ;-)

12:15 danlarkin: :-o

12:15 cemerick: I think the best fix is to make it so that futures use a threadpool whose ThreadFactory produces daemon threads, so that program exit is not hampered by the threadpool holding onto idle threads for N seconds, etc.

12:15 this is, of course, all talk, and there might be reasons why that's not good, or won't work, etc.

12:16 danlarkin: aye... well at the very least now I know why it's happening

12:25 cemerick: I think it makes perfect sense to be able to specify what thread pool a future should execute on as well. That could end up being very important in certain applications.

12:25 hiredman: it's not like futures are complicated

12:25 cemerick: no, certainly not

12:25 hiredman: ~jdoc java.util.concurrentFutureTask

12:25 bah

12:25 ~jdoc java.util.concurrent.FutureTask

12:41 antifuchs: hm, is there a way to destructure into optional args from a & rest argument list?

12:41 danlarkin: [a b & [c]]

12:41 antifuchs: yeah, in the arg list, that's ok... but I need to do it in a let binding form

12:41 cemerick: (let [[a b & rest] restargs] ...)?

12:41 antifuchs: yeah. my question is to get convenient optional args from the rest /there/

12:41 danlarkin: (first restargs)?

12:41 antifuchs: yeah. convenient (:

12:41 that's a no, I suppose (:

12:41 danlarkin: you can do it all in the binding form

12:42 ,(let [[a b & [c]] [1 2]] (list a b c))

12:42 clojurebot: (1 2 nil)

12:42 danlarkin: ,(let [[a b & [c]] [1 2 3]] (list a b c))

12:42 clojurebot: (1 2 3)

12:42 cemerick: yeah, I was just going to do that :-)

12:44 cmvkk: what's the difference between doing [a b & [c]] and doing [a b c] ?

12:44 ,(let [[a b c] [1 2]] (list a b c))

12:44 clojurebot: (1 2 nil)

12:44 danlarkin: more syntax!

12:44 antifuchs: mmmh. [c] works. no default, though...

12:44 cemerick: cmvkk: the former is assuming a seq at the c position.

12:44 antifuchs: (I kept trying with default args)

12:45 cemerick: antifuchs: if you want defaults, you want map destructuring, which requires a map argument.

12:45 antifuchs: "args", I suppose

12:45 cmvkk: cemerick, really?

12:45 cemerick: cmvkk: yeah:

12:45 ,(let [[a b [c d e]] [1 2 3 4 5]] [a b c d e])

12:45 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

12:45 cemerick: ,(let [[a b [c d e]] [1 2 [3 4 5]]] [a b c d e])

12:45 clojurebot: [1 2 3 4 5]

12:46 cmvkk: it's not assuming that 'c' is a seq.

12:46 cemerick: ok, an nth-able object

12:46 cmvkk: but 'c' is a number.

12:47 cemerick: c is a number, but in a vector within the top-level vector

12:48 danlarkin: [a b & [c]] also lets you pass optional args to functions, which would normally complain if they're missing an argument

12:48 cmvkk: but that's only because you used an &.

12:48 cemerick: there's no & in the examples I just invoked

12:48 cmvkk: oh wait, so

12:48 ,(let [[a b c] [1 2]] [a b c])

12:48 clojurebot: [1 2 nil]

12:48 cmvkk: that doesn't work for an arglist?

12:48 danlarkin: if a function takes 3 arguments and you pass two... what happens?

12:48 cmvkk: ,((fn [[a b c]] [a b c]) [1 2])

12:48 clojurebot: [1 2 nil]

12:48 cemerick: I think antifuchs is hoping for a way to have c bound to some default if the existing value is nil.

12:49 antifuchs: rather, if it isn't present in the vector being destructured

12:49 cmvkk: oh I get it now.

12:49 antifuchs: I guess I'm spoiled by destructuring-bind (-:

12:50 danlarkin: cmvkk: in your fn example there that function doesn't take 3 args... it takes one: a vector

12:50 cmvkk: yep.

12:50 cemerick: antifuchs: heh, maybe. You really do want map destructuring, though. Extensive indexed arguments are fragile.

12:50 antifuchs: you could apply it, though. cmvkk - genius.

12:50 cmvkk: i was ignoring the fact that in the let, i was already doing destructuring.

12:50 clojurebot: destructuring is http://clojure.org/special_forms#let

12:50 cemerick: and, small maps aren't hash-maps in clojure.

12:51 ...so, there's not as much of a performance penalty as you might expect using map destructuring over smallish maps (< 16 entries, IIRC)

12:51 clojurebot: map is *LAZY*

12:56 hiredman: map destructuring is great for functions with 3 or more args

12:57 because then you can give earch arg a name instead of just having to get them in the right position

12:57 cemerick: quite right

12:57 kotarak: And for optional values of course, which otherwise should receive a default...

Logging service provided by n01se.net