#clojure logs

2009-03-31

00:17Jedi_Stanniswhat's the difference between while and when in list comprehnsions?
00:17gnuvince_Jedi_Stannis: while stops when the condition becomes false
00:17hiredmanwhile is like take-while
00:17gnuvince_,(for [x [1 3 5 6 7 9] :while (odd? x)] x)
00:17clojurebot(1 3 5)
00:17gnuvince_,(for [x [1 3 5 6 7 9] :when (odd? x)] x)
00:17clojurebot(1 3 5 7 9)
00:17hiredmanwhen is like filter
00:17Jedi_Stannisgot it, thanks
00:17Jedi_Stannisyeah
00:17Jedi_Stannistried a simple example where they were the same at first, and wasn't sure what the difference was
00:21gnuvince_-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?
00:27slashus2gnuvince_: Any luck on performance increases?
00:29erohtaris there a way to get the name of a function from its object representation?
00:29erohtar say - get "println" if you're given println
00:29hiredmannope
00:30hiredmanwell
00:30hiredmanyes, but it would involve a lot of work
00:31hiredmanFns have no names, no names man, they are nameless
00:32erohtarok - makes sense
00:32erohtarwhat is the type of the params when they're sent into a macro?
00:32erohtarare they symbols?
00:32gnuvince_slashus2: yes
00:32gnuvince_slashus2: I cut performance down from 2 minutes 40 seconds to a little under 2 minutes on my home machine.
00:32hiredmanerohtar: depends
00:32gnuvince_slashus2: I completely changed the way parsing was done (the outside interface remains the same however)
00:32erohtar(defmacro macro-name [param1] ())
00:32gnuvince_It's now shorter and faster, but I have this weird reflection call that I can't put my finger on.
00:32erohtarwhat would param1 be?
00:33dnolenit depends on what you call the macro with
00:33hiredmanparam1 is whatever macro-name was called on
00:33dnolenit would be an unevaluated something.
00:33erohtarwhat would its type be?
00:33hiredmanparam1 is whatever macro-name was called on
00:36dnolen,(defmacro return-types [& args ] `(list ~@(map type args)))
00:36clojurebotDENIED
00:36dnolenbleh anyways try that erohtar
00:36dnolenand this
00:36dnolen(macroexpand-1'(return-types asym [1 2 3] {:key :val}))
00:37erohtargot it - its Symbol
00:37erohtarthanks
00:37hiredmanforget types, while useful they are not helping you here
00:37hiredmanif what is passed to the macro is a symbol it is a symbol
00:37hiredmanif it is not a symbol it is not a symbol
00:38hiredmanmacros can take any form the reader can produce
00:38clojurebotHoly Crap.
00:38hiredmanclojurebot: crazy, I know
00:39clojurebotPardon?
00:40hiredman.(:macro (meta delay))
00:40hiredman,(:macro (meta delay))
00:40clojurebotjava.lang.Exception: Can't take value of a macro: #'clojure.core/delay
00:40hiredman,(:macro (meta (var delay)))
00:40clojurebottrue
00:40hiredman,(delay 1)
00:40clojurebot#<Delay@1daed02: 1>
00:40hiredman,(class 1)
00:40clojurebotjava.lang.Integer
00:41hiredman,(delay '(1 2 3))
00:41clojurebot#<Delay@68d91: (1 2 3)>
00:41hiredman,(class '(1 2 3))
00:41clojurebotclojure.lang.PersistentList
00:52danlarkinhow should I determine whether or not I need to deref something, is (instance? clojure.lang.IDeref foo) the best way?
00:55hiredmansounds good
00:55erohtarHow would i get the first thing passed into defmacro as a keyword?
00:56hiredmandepends
00:56erohtarim trying to write a macro that looks like defn, but registers the function in a map also
00:56erohtarfor that, i need the name of the fn being defined as a keyword
00:56hiredmanwhy?
00:56dnolenerohtar you can use anything as a key in a map.
00:56dnolen,{'a 1 'b 2}
00:56clojurebot{a 1, b 2}
00:56dnolenincluding symbols.
00:56erohtaryes, but i want to use the name of the fn as a key
00:56hiredman...
00:56cmvkk,(keyword (str 'a))
00:56hiredmanfns don't have names
00:56clojurebot:a
00:56erohtaryes, but since im trying to create something like a defn, i have the "name"
00:56cmvkkright, and that name is a symbol.
00:56cmvkkyou can then use the symbol as the key in a map.
00:56dnolen,{'a (fn [])}
00:56clojurebot{a #<sandbox$eval__4919$fn__4921 sandbox$eval__4919$fn__4921@96bfda>}
00:56erohtarinside the macro, it doesnt seem to work
00:56cmvkkare you trying to register it in a map from inside the macro?
00:56cmvkkbecause that's probably a bad idea...
00:56hiredmanbecause you are doing it wrong
00:56hiredmanpastbin
00:56hiredmanlisppaste8: url?
00:56lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
00:56erohtaryes... im trying to register it from inside the macro
00:56erohtarcant be done?
00:56cmvkkwhat you need is like (defmacro foo [name & body] `(do (defn ~name ~@body) (register ~name)))
00:56cmvkkthat way, the registering is code that occurs in the expansion
00:58lisppaste8erohtar pasted "untitled" at http://paste.lisp.org/display/77802
00:59danlarkinerohtar: would looking at the ns-publics of the namespace in which you declare the function maybe make more sense?
00:59cmvkkerohtar, you should probably use syntax-quote, it makes macros a lot easier to read
00:59cmvkkjust as an aside
00:59erohtaryes - this is my first real macro writing experience
00:59hiredmanerohtar: are you the guy with the database thing?
00:59erohtaryes
00:59hiredmanif so, don't bother with defn or a macro
01:00cmvkkerohtar, 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
01:00hiredmanjust create a fn and stick it in th map
01:01erohtari tried to defn the function first, because else it wasnt able to evaluate the name
01:01hiredman,(assoc {} :f (fn [x] x))
01:01clojurebot{:f #<sandbox$eval__4925$fn__4927 sandbox$eval__4925$fn__4927@1c2862b>}
01:01erohtarhiredman: yes, i can do that
01:01erohtarah -
01:01erohtarjust using the : will work it?
01:01erohtarsee thats what i need
01:03hiredmanno
01:03hiredmanno
01:03erohtarthen?
01:03hiredmanstop
01:03dnolen,(assoc {} 'f (fn [x] x))
01:03clojurebot{f #<sandbox$eval__4931$fn__4933 sandbox$eval__4931$fn__4933@14708f5>}
01:03dnolen,(assoc {} '+ (fn [x] x))
01:03hiredman,(assoc {} 1 (fn [x] x))
01:03clojurebot{+ #<sandbox$eval__4937$fn__4939 sandbox$eval__4937$fn__4939@aa3e6e>}
01:03clojurebot{1 #<sandbox$eval__4943$fn__4945 sandbox$eval__4943$fn__4945@6f2c06>}
01:03dnolen,(assoc {} [1 2 3] (fn [x] x))
01:03clojurebot{[1 2 3] #<sandbox$eval__4949$fn__4951 sandbox$eval__4949$fn__4951@1fb5664>}
01:03dnolenerohtar they all work.
01:03hiredmananything can be a key in a map
01:04erohtari know that part - but i want the "name" of the function to be the key
01:04dnolenwe've demonstrated that you can do that.
01:04hiredmanno, you don't
01:04hiredmanyou may, but you are mistaken
01:04erohtarwhy do u say that - here's what i wanna do with this
01:04hiredmanbecause functions don'
01:04hiredmant have names
01:04erohtaragreed -
01:04hiredmanso, you cannot have the name of a function as a key, becaue names of functions don't exist
01:04erohtarbut since this particular fn is being defined using a macro which accepts the name also .... there is a logical name i want to use
01:04erohtarin the pastie, service-name is that name
01:04hiredmanit does not accept a name
01:04erohtarhttp://paste.lisp.org/display/77802
01:04hiredmanthere is no such thing as a name
01:05hiredmanthere are symbols
01:05erohtarthere, defsevak is the macro - which accepts service-name
01:05erohtaroh
01:06hiredmanI really recommend you persue a non-macro approach until later
01:06slashus2erohtar: It may be easier if you use a syntax quote.
01:06erohtarheh
01:06erohtarok
01:06erohtarlemme read abt macros a bit more :)
01:06hiredmanget it working with functions
01:06erohtaryup
01:07hiredmana macro is just to make it looki pretty
01:07erohtarfair enuff, thanks
01:07sudoercan i use clojure for web 2.0?
01:07danlarkinsudoer: no
01:07slashus2:-|
01:08hiredmanclojure only works with web 3.0 and above
01:08danlarkinok so I'm confused here:
01:08danlarkin(binding [outer 1] (future (binding [inner outer] inner)))
01:08dnolensudoer: you should look at compojure, it's still early but clojure could be good for the web soon.
01:08danlarkinthat gives, java.lang.IllegalStateException: Var user/outer is unbound.
01:08clojurebot?
01:08sudoerdnolen: yes, I am looking into that
01:09slashus2danlarkin: Doesn't binding work with existing vars?
01:09hiredmancorrect
01:09danlarkinslashus2: yes -- both outer and inner have been def'ed
01:09slashus2okay
01:10hiredmandanlarkin: you need to make a thunk of the binding then run the thunk in the future
01:11slashus2danlarkin: It worked for me.
01:11danlarkinslashus2: it did? Hm, time to svn up clojure
01:12slashus2,(let [*outer* 0 *inner* 0] (binding [*outer* 1] (future (binding [*inner* *outer*] *inner*))))
01:12clojurebotjava.lang.Exception: Unable to resolve var: *outer* in this context
01:12slashus2that won't work
01:12slashus2sorry
01:12slashus2You have to use def
01:12slashus2Don't know why I would have expected that to work.
01:14hiredmanuser=> (binding [outer 1] (future (binding [inner outer] inner)))
01:14hiredmanjava.lang.IllegalStateException: Var user/outer is unbound.
01:15danlarkinhiredman: ((deref (binding [outer 1] (future #(binding [inner outer] inner))))) gives the same error
01:15hiredmanit would
01:15danlarkindid I not thunk the binding?
01:15slashus2(def *outer* 0) (def *inner* 0) (binding [*outer* 1] (future (binding [*inner* *outer*] *inner*))) is the code that I am using
01:16hiredmanslashus2: #<Object$Future$IDeref@c623af: 0>
01:16slashus2yup
01:16slashus2Is that not what he is trying to do?
01:17danlarkinit should be 1
01:17slashus2oh
01:17slashus2:-(
01:17slashus2interesting
01:18hiredmanuser=> (binding [outer 1] (let [f outer] (future (binding [inner f] inner))))
01:18hiredman#<Object$Future$IDeref@33f0de: 1>
01:20hiredmandynamic scope is not closed over by the fn object future makes
01:20slashus2So you have to make a local scope..
01:20clojurebotscope is at http://paste.lisp.org/display/73838
01:20slashus2wow
01:20hiredmanlexical scopre :P
01:20slashus2static scope
01:21danlarkinhiredman: excellent. thanks again
01:23hiredmangood to know
01:23hiredmanI should make sure to remember this
01:26slashus2hiredman: Put it in clojurebot
01:27hiredmanclojurebot: fn?
01:27clojurebotIt's greek to me.
01:28lisppaste8erohtar annotated #77802 "working now" at http://paste.lisp.org/display/77802#1
01:29hiredmanclojurebot: future is <reply>#who: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff
01:29clojurebotRoger.
01:29erohtarthat seems to work as expect, thanks hiredman
01:29hiredmanclojurebot: why doesn't future work?
01:29clojurebotwhy not?
01:29hiredman$%#@%
01:30hiredman~how come future doesn't work?
01:33clojurebothiredman: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff
01:33dnolenhiredman: that's seem like a very interesting case you found, perhaps enough to post on the mailing list?
01:33dnolen,(binding [*outer* 1] (let [*outer* *outer*] (future (binding [*inner* *outer*] *inner*))))
01:33clojurebotjava.lang.Exception: Unable to resolve var: *outer* in this context
01:33hiredmanI dunno that it is actually that interesting
01:33dnolenthe above works so it seems like the binding expression should create the scope so that future calls work as expected right?
01:33hiredmanno
01:33hiredmanbinding should most defintely create a lexical scope
01:33hiredmaner
01:33hiredmannot
01:33hiredmanbinding should most defintely not create a lexical scope
01:33dnolenin which case would providing a new binding not provide it in the current scope?
01:33clojurebotnew Class(x) is (Class. x)
01:33hiredmanno
01:33hiredmanbinding is dynamic scope
01:33hiredmanlet is leixcal scope
01:33dnolenahh
01:33dnolengotcha, just checked
01:33dnolenit's default behavior
01:33dnolenlearn something new everyday.
01:33hiredmanlexical scope is, uh, capturedwhen a fn is created
01:34hiredmandynamic scope when it is executed
01:36slashus2((binding [*outer* 1] (fn [] (println *outer*))))
01:36slashus2I understand
01:37dnolen,(binding [*outer* 5] (println *outer*) ((fn [] (println *outer*))))
01:37clojurebotjava.lang.Exception: Unable to resolve var: *outer* in this context
01:37dnolen,(def *outer* 0)
01:37clojurebotDENIED
01:37dnolen,(let [*outer* 0] (binding [*outer* 5] (println *outer*) ((fn [] (println *outer*)))))
01:37clojurebotjava.lang.Exception: Unable to resolve var: *outer* in this context
01:38slashus2dnolen: That doesn't create a dynamic var.
01:39dnolen,(binding [outer 5] (println outer) ((fn [] (println outer))))
01:39clojurebotjava.lang.Exception: Unable to resolve var: outer in this context
01:39dnolenhaha
01:39hiredman,*outer*
01:39clojurebot1
01:40dnolen,(binding [*outer* 5] (println *outer*) ((fn [] (println *outer*))))
01:40clojurebot5 5
01:40dnolenwhy that?
01:40cmvkk,((let [*foo* 2] (with-local-vars [*foo* 3] (do (print *foo*) (fn [] (print *foo*)))))
01:40clojurebotEOF while reading
01:40cmvkkcrap!
01:40dnolenwhy 5 5 if no lexical scope?
01:40dnolenah because println is an fn call?
01:40hiredmanyou are executing the fn in the dynamic scope
01:40dnolener not ah
01:41dnolenlight goes off
01:41cmvkk,((let [*foo* 2] (with-local-vars [*foo* 3] (do (print @*foo*) (fn [] (print @*foo*))))))
01:41clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
01:41dnolenbecause the var when returned has it binding popped off!
01:41cmvkkoh well.
01:41cmvkkyes.
01:42cmvkk,(let [*foo* 2] ((with-local-vars [*foo* 3] (do (print @*foo*) (fn [] (print @*foo*))))))
01:42clojurebotjava.lang.IllegalStateException: Var null/null is unbound.
01:42hiredman,((binding [*outer* 5] (println *outer*) (fn [] (println *outer*))))
01:42dnolencoolz
01:42clojurebot5 1
01:43dnolengotcha, so future makes sense, the binding has already been removed by the time future execs
01:44slashus2,((binding [*outer* 1] (fn [] (println *outer*))))
01:44clojurebot1
01:44slashus2((binding [*outer* 2] (fn [] (println *outer*))))
01:44slashus2okay
01:44slashus2,((binding [*outer* 2] (fn [] (println *outer*))))
01:44clojurebot1
01:47danlarkinHm... 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...
01:48hiredmanalways?
01:48danlarkinyep
01:48danlarkinthe deref is successful so it's not like it's blocking there
01:48hiredmanGC? threadpool spin down? dunno
01:52danlarkinHmmmm yeah I donno either
01:56hiredman~latest
01:56clojurebotlatest is 1337
01:56replacawow, that's leet! :)
01:57cmvkkthat's been the latest for a few days hasn't it
01:57hiredmanyeah
01:57replacaofficial script kiddie version
01:57hiredmanI was just thinking that
01:57hiredman1.0 is 1337
01:57hiredman:P
01:57replacait will be
01:57cmvkkit's not 1.0 is it?
01:57replacathings are feeling good lately
01:57replacano, not really
01:58hiredmansounds like rich has gone into deep meditation about hierarchies
01:58cmvkki assume, since the last release was just another dated release, that he just gave up on numbered releases entirely.
01:59replacahmm, I think he's still going towards 1.0, but he wants to get some of these issues stabilized first
02:00replacato reduce breaking changes later
02:00hiredman^-
02:00hiredmanhe wants to run free as the wind
02:00hiredmanwhich after promising to not make breaking changes will be hard
02:00danlarkinJSwat calls the main thread "zombied" when it's just sitting there waiting after all the work is done
02:00hiredmanmaybe all the futures are not done yet?
02:01dnolenhiredman: true, but if the hierarchies problem can be solved i think the fundamentals of Clojure will be quite solid.
02:01hiredmanthe main thread finishes but stuff is still runing on the threadpools
02:01hiredman?
02:01Jedi_Stanniswhat's the current issue with hierarchies?
02:01dnolenit'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.
02:02hiredmandnolen: I have yet to care about hierarchies, so clojure is already sollid for me
02:02dnolenhiredman: understandable, but because you don't need to model them. Other people clearly do.
02:02hiredmanbut I hav ebeen following as much as I can of that thread
02:03dnolenJedi_Stannis: it's very difficult to handle to multiple inheritance in any way where ordering the relationships is important.
02:06dnolenJedi_Stannis: there's a lot of hoop-jumping to model the idea of super or even interfaces in pure Clojure as well.
02:06Jedi_StannisI see
02:06dnolenJedi_Stannis: it's tough, multimethods are already really really useful and elegant. ad-hoc hierarchies as well.
02:07dnolenpersonally 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.
02:09dnolenif 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.
02:10Jedi_Stannisyeah, rich seems like a pretty good designer, we'll see what he comes up with
02:11replaca dnolen: what do you think about before and after methods?
02:16dnolenreplaca: 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.
02:17replacadnolen: as long as we could. But yes, I've always liked them more than I used them :-)
02:22dnolenone 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.
02:22replacayeah, makes sense
02:22replacaI haven't been thinking about it as hard as you guys
02:31fffejI'm trying to do some file parsing - is there something like read-string that'll read all the lisp forms of one line?
05:48MikeSethare chats here logged?
05:52Holcxjohttp://clojure-log.n01se.net/date/
10:19antifuchshow can I create an array of floats? I don't need java.lang.Floats, but floats
10:21Cark,(doc make-array)
10:21clojurebot"([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:21antifuchsah. thanks!
10:21Cark,(make-array Float/TYPE 10)
10:21clojurebot#<float[] [F@71a3e>
10:21antifuchsthis doesn't really work with into-array, right?
10:22Carkhum
10:22AWizzArd,(doc into-array)
10:22clojurebot"([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:22Cark,(into-array float/TYPE '(0.1 0.2 0.3))
10:22clojurebotjava.lang.Exception: No such namespace: float
10:22Cark,(into-array Float/TYPE '(0.1 0.2 0.3))
10:22clojurebotjava.lang.IllegalArgumentException: argument type mismatch
10:22AWizzArd,(into-array [1 2 3] Integer/TYPE)
10:22clojurebotjava.lang.ClassCastException: clojure.lang.LazilyPersistentVector cannot be cast to java.lang.Class
10:22AWizzArdhmm
10:22Cark,(into-array Float/TYPE (map float [0.1 0.2 0.3]))
10:22clojurebot#<float[] [F@4d2b18>
10:22Cark,(into-array Float/TYPE [0.1 0.2 0.3])
10:22clojurebotjava.lang.IllegalArgumentException: argument type mismatch
10:22Cark(class 0.1)
10:22Cark,(class 0.1)
10:22clojurebotjava.lang.Double
10:22rsynnottdoes 'float' in this context specifically mean 32bit float?
10:22Cark,(class (float 0.1))
10:22clojurebotjava.lang.Float
10:22Cark,(into-array Double/TYPE [0.1 0.2 0.3])
10:22clojurebot#<double[] [D@94ef06>
10:22Carktadah
10:22AWizzArd,(into-array Integer/TYPE [10 20 30])
10:22clojurebot#<int[] [I@6d74aa>
10:22AWizzArd,(vec (into-array Integer/TYPE [10 20 30]))
10:22clojurebot[10 20 30]
10:22AWizzArdrsynnott: yes
10:22Carkso double is 64bit in java ?
10:22rsynnotthmm, you're not really meant to use those in general, anyway, are you?
10:22AWizzArd,(class (into-array Float/TYPE (map float [0.1 0.2 0.3])))
10:22clojurebot[F
10:22AWizzArdrsynnott: why not?
10:23AWizzArdIt is made easy to create arrays in Clojure.
10:23rsynnottAWizzArd: doubles are faster on modern machines, usually
10:23AWizzArdah okay, I thought you meant Clojure vectors vs Arrays
10:23rsynnottnope
10:24Carkyou'll want to use these for java interop, so i guess it depends on what is expected
10:24rsynnott(in particular, last I heard they were MUCH faster on modern x86s, due to the use of SSE for most FP stuff)
10:24Carkyou mean in general or with java ?
10:24Carkas in : do we know if java uses SSE ?
10:25AWizzArd~google java sse
10:25clojurebotFirst, out of 80700 results is:
10:25clojurebotJava 2 Platform, Standard Edition (J2SE Platform), version 1.4.2
10:25clojurebothttp://java.sun.com/j2se/1.4.2/1.4.2_whitepaper.html
10:25rsynnottCark: I'm not sure if it does
10:25Carklooks like it does =P
10:26rsynnott(but doubles should be faster on modern x87 anyway)
10:31Carki think i neve professionaly used float or doubles ...
10:31Carknever*
10:31Carkmhh actually i did with gdi+ !
10:33cemerickrsynnott: 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:34cemerickI plan on doing some benchmarking with our libraries on that issue, as they use floats *everywhere*.
10:38AWizzArdcemerick: Do you write tests in Enclojure for your Clojure code?
10:42cemerickAWizzArd: we write tests in clojure, and happen to use enclojure, yes
10:42cemerickthat is, enclojure has little to do with the tests we write
10:42AWizzArdDo you use contrib test-is?
10:44cemerickyes, please. :-)
10:45AWizzArdI 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:45cemerickisn't that just an NB library that contains junit?
10:45cemerickoh, nm, I understand what you're referring to
10:45RaynesWhy is it that only Enclojure provides a decent way to automatically build executable jars with Clojure? :|
10:45cemerickthat's just a way to configure your build so that your test files aren't copied into your distribution jar
10:45cemerickRaynes: does it? We've always just rolled our own clojure build process, mostly because we're picky. :-)
10:45rsynnottRaynes: probably people don't see it as a priority to automate
10:45rsynnottit's not as if it's something that most people have to do terribly frequently
10:45AWizzArdWhat 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:47RaynesLa Clojure is kinda nice.
11:11cemerickAWizzArd: 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:28cemerickAWizzArd: 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:41AWizzArdOnly 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:44AWizzArdcemerick: btw, what is a "CI environment"?
11:45cemerickAWizzArd: 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:45cemerickCI == continuous integration
11:45p_lcemerick: start the app by typing (myappname) in REPL. Write code to fix errors that got thrown, type again, go back to writing code ;-)
11:45cemerickheh
11:47AWizzArdcemerick: 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:47cemerickAWizzArd: 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:47AWizzArdyes
11:47cemerickfinally dug myself out from under my mailing list backlog :-)
11:47cemerickI really can't understand the interest in talking about coding conventions in the Java side of clojure.
11:47rhickeycemerick: me neither
11:47cooldude127lol
11:47rhickeyI 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:49cooldude127what's wrong with the clojure java code?
11:49cemerickrhickey: 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:49cemerick"for a particular dispatch value", I mean
11:49cemerickcooldude127: some don't like the formatting and such.
11:49cemerickI don't really, either, but I'd really rather rhickey spent his time and attention on things of significance.
11:49rhickeyslides with factored class diagrams: http://clojure.googlegroups.com/web/tutorial.pdf
11:50rhickeycemerick: yeah, I just wish people could think outside the CLOS box a bit - a la carte hierarchies have a lot of advantages
12:07cemerickrhickey: yeah, those are really helpful...I ended up grokking some things that were very fuzzy before
12:09cemerickrhickey: 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:09clojurebothe works hard so you don't have to
12:09cemerickhiredman: damn, that one worked out well! :-D
12:09cmvkkcan't you do that manually?
12:09cemerickwell, yeah, and I do right now. It's a lot more fragile than call-next-method or super.foo(blah...), though.
12:09cemerickthat's a price worth paying for the a la carte factor, tho.
12:09rhickeycall-next-method has inherent problem IMO, convenient as it may seem
12:09cemerickyeah, they all do, probably more than I know of given my purely "userland" experience
12:09rhickeyI can make it easier, e.g.: (apply (get-method ameth asuper) args), but you'll have to supply the super explicitly
12:11cemerickdanlarkin: future uses the clojure.lang.Agent/soloExecutor thread pool, which uses a 'cached thread pool' from the Executors framework
12:15cemerickfrom 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:15danlarkinHm!
12:15cemerickThreadPoolExecutor (the concrete class behind cachedThreadPool) is parameterized in the timeout that it uses, so fixing this is fundamentally trivial.
12:15cemerickhowever, 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:15cemerickpaging rhickey ;-)
12:15danlarkin:-o
12:15cemerickI 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:15cemerickthis is, of course, all talk, and there might be reasons why that's not good, or won't work, etc.
12:16danlarkinaye... well at the very least now I know why it's happening
12:25cemerickI 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:25hiredmanit's not like futures are complicated
12:25cemerickno, certainly not
12:25hiredman~jdoc java.util.concurrentFutureTask
12:25hiredmanbah
12:25hiredman~jdoc java.util.concurrent.FutureTask
12:41antifuchshm, is there a way to destructure into optional args from a & rest argument list?
12:41danlarkin[a b & [c]]
12:41antifuchsyeah, in the arg list, that's ok... but I need to do it in a let binding form
12:41cemerick(let [[a b & rest] restargs] ...)?
12:41antifuchsyeah. my question is to get convenient optional args from the rest /there/
12:41danlarkin(first restargs)?
12:41antifuchsyeah. convenient (:
12:41antifuchsthat's a no, I suppose (:
12:41danlarkinyou can do it all in the binding form
12:42danlarkin,(let [[a b & [c]] [1 2]] (list a b c))
12:42clojurebot(1 2 nil)
12:42danlarkin,(let [[a b & [c]] [1 2 3]] (list a b c))
12:42clojurebot(1 2 3)
12:42cemerickyeah, I was just going to do that :-)
12:44cmvkkwhat's the difference between doing [a b & [c]] and doing [a b c] ?
12:44cmvkk,(let [[a b c] [1 2]] (list a b c))
12:44clojurebot(1 2 nil)
12:44danlarkinmore syntax!
12:44antifuchsmmmh. [c] works. no default, though...
12:44cemerickcmvkk: the former is assuming a seq at the c position.
12:44antifuchs(I kept trying with default args)
12:45cemerickantifuchs: if you want defaults, you want map destructuring, which requires a map argument.
12:45antifuchs"args", I suppose
12:45cmvkkcemerick, really?
12:45cemerickcmvkk: yeah:
12:45cemerick,(let [[a b [c d e]] [1 2 3 4 5]] [a b c d e])
12:45clojurebotjava.lang.UnsupportedOperationException: nth not supported on this type: Integer
12:45cemerick,(let [[a b [c d e]] [1 2 [3 4 5]]] [a b c d e])
12:45clojurebot[1 2 3 4 5]
12:46cmvkkit's not assuming that 'c' is a seq.
12:46cemerickok, an nth-able object
12:46cmvkkbut 'c' is a number.
12:47cemerickc is a number, but in a vector within the top-level vector
12:48danlarkin[a b & [c]] also lets you pass optional args to functions, which would normally complain if they're missing an argument
12:48cmvkkbut that's only because you used an &.
12:48cemerickthere's no & in the examples I just invoked
12:48cmvkkoh wait, so
12:48cmvkk,(let [[a b c] [1 2]] [a b c])
12:48clojurebot[1 2 nil]
12:48cmvkkthat doesn't work for an arglist?
12:48danlarkinif a function takes 3 arguments and you pass two... what happens?
12:48cmvkk,((fn [[a b c]] [a b c]) [1 2])
12:48clojurebot[1 2 nil]
12:48cemerickI think antifuchs is hoping for a way to have c bound to some default if the existing value is nil.
12:49antifuchsrather, if it isn't present in the vector being destructured
12:49cmvkkoh I get it now.
12:49antifuchsI guess I'm spoiled by destructuring-bind (-:
12:50danlarkincmvkk: in your fn example there that function doesn't take 3 args... it takes one: a vector
12:50cmvkkyep.
12:50cemerickantifuchs: heh, maybe. You really do want map destructuring, though. Extensive indexed arguments are fragile.
12:50antifuchsyou could apply it, though. cmvkk - genius.
12:50cmvkki was ignoring the fact that in the let, i was already doing destructuring.
12:50clojurebotdestructuring is http://clojure.org/special_forms#let
12:50cemerickand, small maps aren't hash-maps in clojure.
12:51cemerick...so, there's not as much of a performance penalty as you might expect using map destructuring over smallish maps (< 16 entries, IIRC)
12:51clojurebotmap is *LAZY*
12:56hiredmanmap destructuring is great for functions with 3 or more args
12:57hiredmanbecause then you can give earch arg a name instead of just having to get them in the right position
12:57cemerickquite right
12:57kotarakAnd for optional values of course, which otherwise should receive a default...