#clojure logs

2009-07-21

00:00hiredmanI guess maybe be a mention of return values would be good there
00:00hiredmanfsm: yes
00:00hiredmanfunction invocation uses the invoke method on IFns, which returns an Object
00:01fsmIs double-array different from make-array Double/TYPE ?
00:01rhickeyif you cross a fn boundary things are passed and returned as objects, your inner loop should be inside one fn
00:01rhickeypassing whole arrays in and out is no problem
00:01rhickeyas arrays are objects
00:02fsmOk I got no speed difference using double-array vs make-array.
00:02fsmI understand the let [] binding method to get a primitive double, let me explain why it doesnt quite work for what I want to do
00:03fsmBasically, all my 3D code revolves around (x, y, z) tuples. Arithmetic operations are usually done to all three at once, in a series (you might add two vectors together and scale the results).
00:04fsmThere will be an explosion of code if you use let [] bindings to pull out the individual values every time
00:04fsmUnless I am mistaken?
00:04rhickeyyou're calling a function to get a single thing out of a vector, that will never be fast until you put your vector, and the aget and its return into the body of a fn - all you are seeing here is boxing overhead and learning nothing about the perf of the primitive ops
00:05rhickeyer, array, not vector
00:06fsmAre you saying, e.g. to assign the result of aget to a variable and then do several operations on that primitive variable?
00:07rhickeydo you have an example of some (small) real thing you are trying to make faster? I really can't make heads or tails of that code
00:07fsmOK sure let me post my actual project, 1 sec
00:08rhickeybut in general, if the array is hinted, the compiler will keep the result of aget primitive as long as it can, so will do with math ops involving other primitives, assignment to other primitive arrays etc. As soon as you pass it across a fn boundary it will box it and primitive game is over
00:08fsmPlease excuse my pidgen-functional programming, this is my first time since haskell in the 90s.
00:08fsmhttp://solardriftwood.com/tracer.clj
00:09fsmYou can see near the top, my little vector math library, that is used extensively
00:09fsmI have tried macros and double arrays with aget but this method had the fastest performance
00:10hiredmanthosemacors
00:10hiredmanthose macros
00:10hiredmanicky
00:11hiredman(sorry to change the subject)
00:11fsmThey are the fastest accessors for the contents of the tuple that I have found
00:11fsmI appreciate their ickyness
00:11hiredmanyou are evaluating the args to the macros multiple times within the macros
00:11rhickeyIf you want the fastest math you will need primitives and primitive arrays right now
00:12rhickeyroughly 20x faster than boxed arithmetic
00:12fsmYes, I switched my code to primitive arrays
00:12fsmI changed makeVect to use make-array Double/TYPE
00:12fsmand I changed my vx vy vz macros to (aget array index)
00:12fsmand I got 30% slower
00:13rhickeyarray and index were primitives?
00:14hiredmanfor example, (makeVect [1 2 3]) turns into [(nth [1 2 3] 0) (nth [1 2 3] 1) (nth [1 2 3] 2)] instead of something like (let [foo [1 2 3]] [(nth foo 0) (nth foo 1) (nth foo 2)])
00:14rhickeyyou need to make sure every participant in the computation is primitive, otherwise you will actually do more boxing
00:14fsmI changed to this macro
00:14fsm(defmacro makeVect [x y z] `(let [v# (double-array 3)] (aset-double v# 0 ~x) (aset-double v# 1 ~y) (aset-double v# 2 ~z) v#))
00:15arohnerrhickey: would it be possible to make a "warn-on-slow-math" flag, similar to warn on reflection?
00:15fsmAnd this macro for accessor (defmacro vx [vect] `(aget ~vect 0))
00:15fsmAnd yet, these changes caused a performance drop
00:16fsmI also tried this for my accessor macro (defn vxwithhint [#^doubles vect] (aget vect 0))
00:16fsmAnd that gave the same speed as using [] and nth
00:18rhickeyI think your problem might be in constructing the array tuples
00:19rhickeyyou definitely do not want to create a vector in order to create an array
00:20fsmYes
00:20rhickeyyou can keep an array of 3 zero's around and clone it in make-vect
00:20fsmThat second form with all the nth horror, that is only used rarely in some non performance critical places
00:20rhickeythen aset the members
00:20rhickeyyou cannot use nth, only aget
00:21fsmThe one that hiredman is referring to
00:21fsmThe problem is how to cleanly express (vecAdd v1 (vecSub v2 v3)) and get primitives used
00:22fsmWhere v1, v2, v3 are tuples of three double values
00:22rhickeyv1/2/3 have to be double-arrays
00:22fsmI found using double-arrays to have same performance as [] and nth, presumably because of boxing
00:23rhickeythen vec-add can hint (defn vec-add [#^doubles v1 #^doubles v2] ...)
00:23fsmYes, when I did that, I got the same performance as using [] and nth
00:23fsmI swear
00:23duncanmheh
00:24fsmThat is why I wrote the testdouble.clj to evaluate these alternatives
00:24rhickeythat doesn't indicate anything about arrays, just that you didn't have everything primitive
00:24fsmIndeed
00:24rhickeyso, first you need a fast make-vect
00:25fsmwhat about makeVect and vx macros in my testdouble.clj?
00:26duncanmno need to write any macros, right?
00:26duncanm(defn make-vect [x y z]
00:26duncanm (let [v (make-array Double/TYPE 3)]
00:26duncanm (aset v 0 x) (aset v 1 y) (aset v 2 z)
00:26duncanm v)) ;; is this fast?
00:27fsmThat is what I have, except i call aset-double
00:27fsmAnd consider my vxfn for a non-macro version
00:27fsmof vx *
00:27duncanm23:53 <rhickey> "aget/aset are overloaded for arrays of primitives"
00:28fsmaset is not overloaded on my clojure install
00:28fsmI get a comple failure
00:28fsmcompile*
00:29fsmPerhaps my clojure is out of date, but the net result should be the same
00:30notostracaAnyone here interested in Clojure for... games?
00:31duncanmfsm: which version are you running?
00:33fsmI have the macports version, 20081217_0
00:34hiredmanwow
00:34hiredmanthat is old
00:34fsmHm, that is the trouble with macports
00:34fsmI will install the latest version and re-test
00:35rhickeylisppaste8: url
00:35lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
00:35lisppaste8rhickey pasted "fast make-vect" at http://paste.lisp.org/display/83896
00:42duncanmrhickey: if make-vect were a function, it'd be slower?
00:43rhickeyduncanm: x y z would have to be boxed
00:45fsmOK, same results on clojure-1.0.0
00:45fsmI saw your fast make-vect
00:45fsmThe next problem is how to access the contents of that vector without boxing
00:46fsmI know I can use let binding to assign the result of aget to a double
00:47fsmBut, then the question is how to cleanly write a vecAdd function to add the elements of two arrays together
00:47hiredmanall the operations would have to be macros that emit calls to things that handle primitives
00:48fsmYes
00:48hiredmanor just use aget
00:48fsmBut how to pull the primitives out of the array without them being boxed/unboxed?
00:48fsmI did that, result was boxed
00:49fsm(guessing from the calls to Number.ops)
00:49fsmso if I have two java double arrays (1.0 2.0 3.0) (4.0 5.0 6.0) how can I end up with a java double array (5.0 7.0 9.0) (i.e. sum) without boxing/unboxing?
00:50duncanmrhickey: is the only way to pass primitives around is to avoid Fns and use macros?
00:50fsmThe only way I can see is to use amap perhaps?
00:50fsmBut that doesnt work for functions like dot and cross product, that require access to the elements of the arrays in all kinds of funky orders
00:51fsmAnd then even the result of amap/areduce would be boxed I guess, meaning another box/unbox for any operation on the resulting value
00:53hiredmanfsm: so you want something like (makevec (+ (aget v1 0) (aget v2 0)) (+ … so you just write a macro that emits that code
00:53fsmYes, I wrote my macros to do that
00:53fsmBut that caused boxed arithmetic functions to get called
00:53fsmI checked with macroexpand
00:53fsmAnd the profiler
00:54fsmSorry to cause the tech support call from hell to you guys
00:54fsmI really enjoyed learning clojure so far
00:55fsmIf you see my vx macro in testdouble.clj it does what you suggest
00:55fsmbut the result of (+ (aget v1 0) 1.0) is a call to Number.ops
00:57duncanmfsm: how can you tell that?
00:58lisppaste8rhickey annotated #83896 "vec-add" at http://paste.lisp.org/display/83896#1
00:58rhickey20x faster than vecAdd
01:00rhickeyfsm: a 1.0 literal is not a primitive double, use (double 1.0)
01:02fsmOK let me do some testing
01:02fsmbrb
01:02rhickeyI think your time will be dominated by array allocation
01:10fsmOK here is a tricky finding
01:10fsmThat vec-add function up there results in calls to unchecked-add
01:11fsmBut when I change the numbers in the vectors to floating point by putting a .0 on the end
01:11fsmMy old friend Number.ops reappears
01:11fsmand performance drops 50%
01:12fsmAnd I have to change aset for aset-double
01:12hiredmanuh
01:12hiredman 22:01 rhickey : fsm: a 1.0 literal is not a primitive double, use (double 1.0)
01:13fsmoops
01:14hiredmanmy understanding is when done properly, aset will always be faster than aset-double
01:21fsmOK, I did some poking around, it looks like adding two doubles results in a call to Numbers.add() which should hopefully resolve to the version that takes two doubles
01:21fsmI am going to plug this stuff into my raytracer and compare the performance
01:25Jomyoothow would i define line-height for .emacs.el
01:28thearthurhow can i clear all the deftest'ed tests in all namespaces?
01:28Jomyootwhich emacs project brow3ser do you guys use for clojure?
01:39thearthuris there a clojure-contrib chat room also?
01:39fsmOK, I retrofitted the fast vector code to my raytracer
01:40fsmA 10% performance drop over [] and nth
01:40fsm:/
01:40fsmMaybe the use of macros is causing me to blow out the cache
01:48fsmThe same result as my own attempt to use double-arrays, so there it is
01:48fsmThanks anyway everyone
02:45kylesmithDoes anyone know how to print structures with circular loops? I have a structure that has an atom for the parent and children. When I try to print it at the repl, I blow the stack. I'm guessing it's trying to print the children, then the parent, etc etc.
02:47kylesmith(I wrote this code when I first learned clojure, so it sucks.) Zippers are able to access the parent implicitly, so should I just give up and rewrite it?
02:50fsmAny of my ray tracing helper friends still around?
03:13yangsx(my-fn (first my-coll)) gives me expected results, but (map my-fn my-coll) gives NullPointerException at LazySeq.java:47 because my-fn has to do IO processing. I know that's a problem related to laziness, but don't know how to avoid.
03:13jdzyangsx: try doall or dorun
03:14yangsxjdz: (doall (map my-fn my-coll)) does not help.
03:16jdzis it in the same place in the code as the simple my-fn invocation that works?
03:24yangsxjdz: yes. I'm using slime interactively. I think laziness is off with REPL and that's why doall/dorun do not solve my problem.
03:24jdzwhat do you mean "is off"?
03:25yangsxjdz: I thought it's eager.
03:25jdzthe repl is besides the point here, really.
03:25jdzif my-fn does i/o, then it must have the stream open
03:26jdzthat's all there is to it
03:26jdzif you have to process my-coll with my-fn, then do it with doall where the stream is open
03:30yangsxjdz: my-fn calls another function, which has (with-open [..] (do-all ..)). It's strange it should fail with my-fn, but other functions calling it works as expected.
03:31yangsxwork*
03:31jdzwell then you'll have to provide the code (using lisppaste)
03:36yangsxjdz:thanks for the help; have to sort unrelated code first
04:42Fossihi
04:47kylesmithWould anyone like to help me out with some performance optimizations?
04:52rottcoddis it possible to go up directories when loading files? eg (load "../foo")
04:56jdzrottcodd: that will be relative to the working directory of your JVM
04:57rottcoddjdz: so it doesn't search the classpath?
04:58jdzload does not
04:58jdzclasspath is for namespace-related functions
04:58jdzlike require, use, import
05:17jdzrottcodd: actually, i have misinformed you.
05:17jdz,(doc load)
05:17clojurebot"([& paths]); Loads Clojure code from resources in classpath. A path is interpreted as classpath-relative if it begins with a slash or relative to the root directory for the current namespace otherwise."
05:22gkoIn Classpath means in a .jar ?
05:23jdznot necessarily
05:23jdzone can put either .jars or directories in classpath
05:28gkoLooks like file must be named like: a_b_c.clj
05:28gkoand not: a-b-c.clj
05:28jdzwell, you should know that: http://clojure.org/libs
05:29gkooh... my bad..
05:31jdzlearn something new every day :)
05:31gkoIs the general rule: "use" for libraries, "load" for own code?
05:31gko:)
05:31jdzi don't use load at all, yet
05:31jdzload is helpful if you want to split a nampespace into many files
05:34gkook
06:09JomyootDear Emacs users in this channel. Do you guys use any project management or project browser plugin for emacs?
06:18rottcoddJomyoot: I don't bother, the tools I use most for browsing code are M-. (slime-edit-definition) and M-, (slime-pop-definition-stack)
06:19JomyootWhat if you have codes in different files different folders?
06:19Jomyootvery deeply located folders
06:20Jomyoothow do you quickly manage all these definitions
06:20jdzsame
06:20rottcoddM-. will find any definition that is loaded
06:20Jomyoothmm
06:20Jomyooti will hopefully learn soon
06:21Jomyootbut for a newbie. transitioning in from being used to IDE. Do you guys think ECB is good?
06:23JomyootI might go as far to ask: does Slime provide code completion both for Clojure and Java Interop?
06:30hd_hey, i got errors while building clojure from git repository. These are the errors http://pastebin.com/d18261d17. Any idea?
06:32rottcoddJomyoot: have you looked at enclojure: http://www.enclojure.org/
07:29Fossiis there a library yet that generates documentation for a directory path (using gen-html-docs or such)?
08:32fsmHi. Floating point performance solved in my raytracer.
08:32fsmI misread this line "All arguments are passed to Clojure fns as objects, so there's no point to putting non-array primitive type hints on fn args."
08:33fsmMissed the 'non-array' part.
08:33carkoh nice
08:33fsmThanks everyone, that improved my vector routines speed 5x and my raytracer improved by 25%
08:33fsmI did some profiling and made an overall speed boost of 100%
08:33Chousukenice.
08:33cemerickexcellent :-)
08:34Chousukeare you doing this on clojure 1.0?
08:34fsmYes, I am now.
08:34cemericklooks like the "math as fast as java" claim is being borne out
08:34Chousuketrunk has some neat new stuff that might make things even faster.
08:35Chousukealso, did you try the new escape analysis features in JDK 1.6b14?
08:35ChousukeI'm still interested in seeing how it affects "real" code
08:35fsmHere is a sample image of testing depth-of-field effects: http://solardriftwood.com/dof.png
08:35fsmJust for fun.
08:35fsmI think I am restricted on java versions, being on osx
08:36Chousukeoh. yeah, only 1.6b13 for os x for now :/
08:36cemerick1.6_13 is the latest on OS X, AFAIK
08:37fsmI just checked, I am on 1.5, I am going to switch to 1.6 and compare
08:37jdzwhat's left is to publish the source and let somebody else do the benchmarking :)
08:37Chousukefsm: there's no escape analysis on the OS X version of 1.6 yet though :/
08:38cemerick1.6 *is* faster than 1.5, though. Not orders-of-magnitude, but still...
08:38Chousukeoh wait
08:38Chousukethere's a developer preview on ADC
08:38Chousukeapparently has 1.6.0_15
08:39fsmI will publish the source into public domain once I have improved the quality and added some features
08:39Chousukehm, public domain is problematic
08:39Chousukeuse MIT or something instead :P
08:40ChousukePD is a problem because it's ineffective in some jurisdictions AFAIK :/
08:43Chouserwas rhickey really in here until 1am EST?
08:44cemerickclojurebot: ~rhickey
08:44clojurebot"The guy is totally awesome." -- Daniel Weinreb
08:44cemerickclojurebot: ~rhickey
08:45clojurebothe works hard so you don't have to
08:45cemerick:-)
08:45Chouser~seen rhickey
08:46clojurebotrhickey was last seen joining #clojure, 31 minutes ago
08:46jdzclojurebot: I totally agree (with you and Dan)
08:46clojurebotTitim gan éirí ort.
08:46jdzye, whatever
08:47jdztalking to bots is fun
08:50fsmInteresting, Java 1.5 vs 1.6 and Clojure 1.0 vs 1.1 alpha, performance difference is under the noise floor for my short tests
08:50fsmI will try ADC preview later
08:51jdzclojurebot: ~rhickey
08:51clojurebotrhickey is totally awesome!
08:51jdzi win
08:52jdzdamn, i'm repeating Dan
08:52jdzclojurebot: ~rhickey
08:52clojurebotrhickey is totally awesome!
08:52jdzhmm
08:59Chouserreading "iterators must go" http://lambda-the-ultimate.org/node/3520
09:00Chouserbeautiful and condemning analysis of C++ STL iterators
09:01Chouser3 slides into the proposed solution and state sneaks right back in.
09:01cemerickwhew, just the thought of hacking C++ is scarier to me than ever (now that I'm completely steeped in clojurey-goodness)
09:05fsmIs this an acceptable forum for C++ bashing?
09:05fsmIf so, I would like to bash C++.
09:05Chouserit is interesting how much these "ranges" seem to be targetted at solving many of the same problems as the seq library
09:06ChouserI suppose if you operate them over immutable collections they'd be fine...
09:06cemerickyeah, 'cause those are all over the place in C++
09:08cemerickI guess I shouldn't be so harsh. (Almost) all my C++ work has been in connection with various FFIs, which certainly made things a lot more painful than they probably would be in a real C++ app.
09:09Chouseroh, immutable collections? Yeah, never seen one in C++.
09:09rhickeyChouser: I argued against STL iterators to no avail when they first came out. At the time I especially hated that they came in two disconnected parts. The pressure to retain the pointer model was intense
09:10Chouserrhickey: did you see this paper? That's exactly what he's doing differently -- start and end tied together
09:10rhickeyChouser: yes, saw it and sighed
09:11rhickeynow what, 15 years later?
09:11Chouserbut I guess I was observing that though ranges fix some of the syntax pain of iterators, the truly deep and panicky pain that iterators have caused me are more due to the mutable collections than the iterators themselves
09:12Chouserrhickey: I keep forgetting you were deep into C++
09:13rhickeythat, and the fact that they really can't serve as elements of interfaces. I.e., how many Java APIs do you see that take/return Iterators? They are for inside-a-function use only
09:17rhickeyGuy Steele argues against Lisp lists and sequential processing in general here: http://groups.csail.mit.edu/mac/users/gjs/6.945/readings/MITApril2009Steele.pdf
09:19rhickeya bit hard to follow from the slides, but Clojure is well positioned here as few people keep their important data in lists in Clojure. The vectors/maps/sets are set up for parallelization
09:20fsmHello Richard, I got my head around my floating point issues, many thanks.
09:20Jomyoothow to always turn paredit-mode on ?
09:21fsmI had misread the rule about avoiding type-hinting function arguments.
09:21rhickeyfsm: sure. I'm not sure you will get the most blazing perf using small vectors/arrays as points in Java/Clojure due to the allocation vs say in C++ where they could be value types
09:22rhickeybut you should be able to match Java in any case
09:23fsmYes, performance is constrained mainly because in C/C++ you get intel's libraries which render such 3d math operations into SSE
09:23fsmHowever, I did get a 30% speed boost once I figured it out, and then with some profiling, an overall 100% boost, still more work to do
09:23rhickeyfsm: great!
09:24cemerickthat's roughly our biggest single hotspot as well -- spatial indexing of 2D shapes isn't as demanding as ray-tracing, but I suspect the allocation patterns are similar
09:24rhickeywhat about keeping each set of Ds in it's own array?
09:25rhickeyits
09:26cemerickeh, we're trying to not get overly clever yet
09:26fsmOK, I am going to leave a big render going and get some sleep. Thanks again.
09:27cemerickwe've done enough perf work to make everything else tolerable -- we need to build about 4 more levels on top of what we have now before we stop to take a look at perf in a serious way
09:28rhickeyin my audio work I'd always split and stripe arrays of aggregates - instead of [{x y z} {x y z} ...] [x x ...] [y y ...] [z z ...]
09:28cemerickworst case scenario is that we buy a couple more U's of CPU until we do an incremental rev on the final product.
09:28rhickeybut it is a pain to manage
09:28AWizzArdOne thing I will do is profiling our AI engine in a few weeks and finding out where the time is spent. I would like to hear your opinions, if there is potential room for improvements.
09:29cemerickyeah, I'd like to preserve a proper DOM without doing backflips with the bookkeeping -- though we'll do whatever we can when we get to the optimization part
09:29rhickeywell, I'm convinced parallel ops on vectors/sets/maps will be a big win for Clojure, and then it's just a matter of more multi in your multicore
09:30rhickeytoday I hope to put a granularity knob on the pvmap/pvreduce stuff I showed you yesterday
09:30cemerickwell, I've experimented with using a base class for all of the coordinate fields of each shape, and it provides a huge boost -- I suspect new-new will compile down to the same thing
09:31cemerickbase Java class, that is
09:31ChouserThat Steele pdf is quite interesting.
09:31rhickeyalso will expose fork and join, so you can build multi-call nested aggregate parallel operations and feed the same pool
09:32Chouseris it fair to say the length stored for each node a vector essentially represents his new "base case" for interior tree termination?
09:32cemerickI saw a link somewhere with the latest (bad?) news about fork/join in jdk7, but can't find it now...
09:32rhickeyChouser: yeah, but I don't think using binary trees as lists is that compelling. The bigger story is trees in general, and Clojure is in good shape there
09:32rhickeycemerick: I'd like to see that link
09:33Chouseryes -- log32 is fantastic for trees, vs. log2
09:33cemerickrhickey: heh, I thought you had pasted it :-P
09:33rhickeyChouser: and using trees for vectors and hash tables
09:33cemericksomething about a particular JSR not going to be ready in time?
09:33Chouserboth theoretically ("essentially constant time") and practically for how cache lines work.
09:34rhickeycemerick: huh, I've been working with FJ all weekend in response to a request to provide some input
09:35cemerickach. Perhaps I'm more confused than usual.
09:35cemerick(there's a lot of JSRs flying about lately)
09:35cemerickor, news thereof, that is
09:36rhickeyyeah, I do know ParallelArray is out, and that's a great thing as it forced me to look at applying FJ directly to Clojure's data structures.
09:40Chouserpvreduce eliminates the "SUM=0" from reduce that Steele describes as bad.
09:40Chouseras of course it must
09:41Chouserworking on Clojure and working in Clojure have very different profit structures. :-/
09:42rhickeyChouser: exactly. I was wondering if those doing the latter might be willing to, e.g. pay for 'support' contracts so I can continue to do the former
09:42rhickeysome more writeoff-able than donations
09:43rhickeysomething
09:43Chouserseems plausible, but dunno if we're there yet.
09:43rhickeyright, the tricky part is surviving from here to 'there' without getting sucked into something else
09:44ChouserI'm at maybe 20% of my time writing Clojure instead of C++, but nobody here is committed to it -- extra cost would simply be a reason to remove that 20%
09:44Chouseryeah, I understnad.
09:56AWizzArdrhickey: btw, is there still no one working on Fingertrees?
09:56rhickeyAWizzArd: I'm not
09:57AWizzArdI will see if I can talk a Haskell friend into it. He is interested in Clojure and tree structures :-)
09:57rhickeyI'd love to have cinc and newnew in order to be able to write it in Clojure rather than Java, but you could use proxy and just swap in newnew to make it faster later...
09:57rhickeynewnew will not be called newnew
10:01rhickeyre: newnew and mutable locals, one concept I had early on was to make it so that mutable locals could not be closed-over. The problem is, that creates an asymmetry, getting around which requires a box. That is the story with Java's inner classes
10:01AWizzArdhmm
10:02rhickeyother langs supporting closures and mutable locals secretly create a box for you and all closing-over fns share the box. This is the source of toy OO examples in Scheme's etc
10:02rhickeythe third option, dunno if used anywhere, if for each closure to get its own mutable 'hole', not shared
10:04AWizzArdBut mutable locals will come?
10:04rhickeythe logic is, closing over a value gives you a value with that name, closing over a hole gives you a hole with that name, *not* a reference to a hole
10:06rhickeysince creating member fields in newnew is done by closing over let-bound locals, let would need to be able to create a mutable binding, let's say like (let [x (volatile 42)] ...)
10:07rhickeywhat I am considering is that any closure over x would get its own volatile x with no connection to the others
10:07Chouserrhickey: so ... multiple closure instances in the same let would get separate mutables?
10:07rhickeyright
10:08rhickeyin the 'normal' case of newnew there would only be one closure
10:08rhickeybut there would be no shared holes in the environment, a huge plus for me
10:09rhickeyand no allocation for a box, so a true replacement for mutable fields
10:11ChouserFrom my experience teaching old time C++ coders to use JavaScript, that's actually the behavior for closures that they expect.
10:13shooverJomyoot: (add-hook 'clojure-mode-hook (lambda () (paredit-mode 1)))
10:13Chouserwould local mutables be mutable outside of a newnew?
10:14ChouserI mean... (let [x (volatile 42)] (set! x 96)) would work?
10:16rhickeyChouser: yes, I think set! would become aware of volatiles
10:17rhickeythey would be as dangerous as Java volatiles, and have the same threading semantics
10:17rhickeyvs unadorned mutable fields in Java
10:17Chouserhm... extending let to do mutables feels almost worse to me than extending newnew to do interfaces.
10:18Chouserit the only purpose is for mutable newnew fields, can they just be added to newnew?
10:19rhickeyChouser: but newnew works like this: (let [x 42 y 13] (newnew [Foo] [] (amethod [] ... x ... y))
10:19ChouserI was thinking the syntax to the newnew special form doesn't have to be pretty... between fn, defn, destructuring, etc. nobody would have to use newnew's own syntax directly.
10:20Chouserrhickey: I know that's the plan, but it makes a hole: (let [x (volatile 42)] ..do-evil-things.. (newnew ...) ..more-evil-things..)
10:20rhickeyChouser: leveraging the concept of closure for fields is a nice unifying principle. Having a separate way to name fields makes for a duality similar to Java's and a lot of muck
10:21Chouser(let [x (volatile 0)] (while (not= x 20) (println x) (set! x (inc x)))
10:21rhickeyyeah, ugly
10:21Chouserthere! now I don't need to learn all this crazy high-order stuff.
10:22Chouserbut I guess if you're committed to that, you can do it with refs or atoms now.
10:22rhickeyright
10:23rhickeyand higher-order has to win on its own merits, i.e. dotimes vs the above
10:23Chouserand it does, so I guess that's ok.
10:23AWizzArdWhat is the advantage of mutable locals (vs the use of atoms)?
10:24rhickeyAWizzArd: they can't be shared
10:24Chousersurely somebody has played with building closures like your "unshared hole" idea. I wonder if there are pitfalls I'm not seeing.
10:25rhickeyChouser: people coming from Scheme/CL would definitely be confused by the lack of sharing
10:26rhickeyof course, and closure allows for sharing, and multiple calls to the same closure from multiple threads is a definite problem at the Java Concurrency in Practice level
10:26rhickeyand/any
10:26Chouserhuh. I was thinking of (let [x (volatile)] (take 10 (repeatedly #(newnew ...)))) and how nice that they each get their own x
10:27rhickeyChouser: I agree totally, but that's not how it works today in Lisps, nor ever
10:27Chouserbut I can see that it would be surprising for (let [x (volatile)] (newnew A ...) (newnew B ...)) to not share
10:27rhickeywhich is fine by me, that's why I left out mutable locals the old way
10:27Chouseresp. since the multiplt methods within A *would* share.
10:28Chousermultiple
10:28rhickeyChouser: yes, but the whole (newnew) thing is kind of new, so expectations should be weak
10:28Chouseryes
10:29rhickeyand volatile is a great disclaimer
10:29rhickeywatch out!!
10:29rhickeydangerous explosive variable
10:29Chouserinteresting to put it on the value rather than the local name. looks like any of the reference type constructors, but of course isn't at all.
10:30rhickeyif you don't have JCIP-level skills in Java you should never use volatile in Clojure
10:30jdz☣volatile☣
10:30rhickeybut I do, and have to in order to write Clojure, and currently need to leave Clojure to do so
10:30rhickeyChouser: I'm completely unsure about the syntax
10:30Chouserok
10:31rhickeymay even be (let-volatile [x 42]...
10:33rhickeyin any case, unshared volatiles are the only way I would consider them for Clojure, so looking for feedback about the confusion/expectation issues
10:33rhickeyIt does fly in the face of the history of 'environments', but IMO they always had a faulty story re: values vs places
10:34ChouserSince the scope of the shared part is a single newnew, I do think it might be less confusing to have them declared syntactically inside the newnew but outside the method defs
10:34AWizzArdwhat is jcip?
10:34danlarkinAWizzArd: java concurrency in practice
10:35AWizzArdah oki, thx
10:35rhickeyChouser: still trying to get them out of let? : )
10:35ChouserI understand the unifying argument, but unsure if I find it compelling.
10:36Chouseryessir!
10:36rhickeyI'd have to audit the code to see if there were any places in Clojure's implementation where I *needed* a mutable local and couldn't afford to allocate something like an AtomicReference. Likely...
10:36Chouser(let [x (volatile 1)] (set! x 2) (newnew ...))
10:37Chouserthat newnew object has a mutable field it can call x -- it starts with a value of 2?
10:37rhickeynewnew's x starts at 2 and has an independent lifetime thereafter
10:37Chouserok
10:38rhickeyExpectations aside, I don't think the behavior is tricky
10:39rhickeyI just hate to have another concept for 'fields', but maybe we'll be forced into it...
10:40rhickeybasically, volatile is for experts only
10:40Chouser(newnew :extends AFn :mutable [x 42] (invoke [] (println "My x is " x))) ; just a pretend syntax for discussion
10:41Chouser((newnew :extends AFn :mutable [x 1] (invoke [] (set! x 2) (newnew ...)))) ; hey look, I did it anyway!
10:41rhickeyexactly
10:42Chouserat the expense of uglier syntax in all cases, plus an extra allocation when AtomicReference was "unaffordable" :-P
10:42AWizzArdBtw, is all this mutable locals stuff, and newnew and so on, for rewriting Clojure in Clojure?
10:42rhickeyand people aren't writing (newnew [AFn]...), they are writing (defn foo [x]), putting pressure to lift the :mutable to arglists
10:43Chouserwhat!? when would defn get a mutable?
10:44rhickeyonce you have a volatile in scope, how to deal lwith it in nested scopes becomes an issue. There really isn't a difference between a let body and a fn body and a class implementation in terms of privileges, necessity, safety or desirability of a mutable
10:45rhickeyChouser: it wouldn't, but if the only was was in newnew, and people don't want to write (newnew :extends AFn etc ...
10:46rhickeythe only mutable was in newnew
10:46ChouserAWizzArd: I find it uncomfortable when a language provides features that I can't write myself in the language. This starts with types, so you get C++'s ability to define classes, overload operators, etc. Ruby takes you further with some ability to create flow control mechanisms. Lisps's macros of course are another whole category of power.
10:47ChouserAWizzArd: Clojure today goes a long way because of macros, proxy, etc. but I still can't write, for example, finger trees that are competitive with Clojure's builtin collections without dropping to Java. I'd love to see that fixed. newnew (and mutable locals) would fix that.
10:49Chouserrhickey: I assume an inner newnew would again get its own mutable -- you expect that to be undesirable?
10:49rhickeythere are 11 volatiles in Clojure - all in ref types and caching seqs
10:50rhickeyChouser: no, desirable, just not really different than volatile in let
10:50rhickeythere are some other mutable locals under the scope of synchronization, harder to search for
10:51rhickeymaking them volatile would be harmless
10:52Chouseroh, right. yeah, the only argument I've got left is making the syntactic scope match the sharing scope.
10:52Chouserthat's probably sufficiently countered with the "expert-only" nature of the thing.
10:53kylesmithWould anyone care to help me with some performance optimization?
10:54rhickeyChouser: but if scopes matched like that we wouldn't have closures, we'd have to redeclare everything in each nested scope
10:55rhickeyI admit that inheriting a 'hole' is weird though
10:56Chouserhm, yes.
11:01lisppaste8Anniepoo pasted "untitled" at http://paste.lisp.org/display/83921
11:01AnniepooI'm having noobie problems compiling to disk
11:03ChouserAnniepoo: your file must be named foo/edu/hhp/sl/automation/lessonPrimEditor/ui/LessonPrimPane.clj and foo must be mentioned in your classpath
11:04AnniepooI believe both of those are true
11:04AWizzArdChouser: I see. So, mutable locals are mutable objects with Java speed.
11:04AnniepooI'm wondering where the repl in La Clojure is picking up classpath
11:05ChouserAWizzArd: a Clojure mutable local would be like a regular Java instance field
11:06rhickeyif volatile was part of newnew, I'd move back to the school of 'closing over it captures its value' (immutably), or, perhaps, is disallowed (like in Java), and similarly you could copy it into an immutable binding and close over that
11:07hamzais there a way to create an array an set its elements initial value i am creating an 2d array thats 1000x1000 elements and loopint through it and settings all its elements to zero takes more than 30 secs?
11:09Chouserrhickey: ohh.. I wasn't thinking about inner newnews that were created via, say, #()
11:10Chouserrhickey: so with let-volatile you might use #(set! x y) inside somewhere, while with newnew-volatile you'd have to do something more complicated inside.
11:10Chouser...most likely just avoid the higher-level function and do it with loop/recur
11:12Chouserdon't java arrays promise to be zeroed out when created?
11:13hamzathats what i thought but after creating checking some random indexes returns nil as their value
11:13hamzathats why i am trying to zero them.
11:14AWizzArdhamza: did you try to-array-2d?
11:15Chouserhamza: oh, you must have an array of Objects. Did you want an array of ints instead?
11:16hamzai use (def atest (make-array Integer/TYPE 1000 1000))
11:16hamzahow can i create an array of ints?
11:16Chouseryou've got it.
11:17Chouser,(aget (make-array Integer/TYPE 1000 1000) 5 5)
11:17clojurebot0
11:18hamzathx when i tested this i got nil no idea why now i get zero
11:19hamzakk my prev. decleration was (make-array Integer 1000 1000) thats why i got nil.
11:20Chouseryep, that'd do it.
11:22hamzaone more question at some point i have to iterate over this array for now i am using doseq to iterate is there a faster way to do this like using higher level functions?
11:23Knekkwhile we are on the subject, how would I crate an initialize an array of structures then?
11:24Chouserhamza: you might look at amap
11:24Chousukeamap clones the array though
11:24Chouseryes!
11:25Chousukeyou probably want to avoid that if you're initializing it :P
11:25Chouseroh
11:25Chouserwell, I was answering hamza, not Knekk
11:25Chousukeoh, heh.
11:26ChousukeI didn't even realise there were two people talking about arrays :P
11:26KnekkI just piped in with a question
11:26ChousukeKnekk: an array of structs is just an array of Objects
11:27Knekkmake-array takes an Object type, right, so I'd use (type structname) ?
11:28Chousukehmm
11:28ChousukeI don't think that would work.
11:28Knekkwell, it doesn't complain
11:28Chousukeyou'd need (type (struct structname "some" "dummy" "vals"))
11:28Chouseranyway, I guess you're outside my realm of experience now. But the things to look at are amap, areduce, loop/recur, primitive locals, while keeping an eye on the mutable vector and pvmap, pvreduce stuff
11:28Knekkbut I can't aset the array elements
11:29ChousukeKnekk: the structname has type clojure.lang.PersistentStructMap$Def
11:29Chousukethe actual struct type is probably different.
11:29Chousuke... a PersistentStructMap, I would guess :P
11:30Knekkyeah
11:30Chousukerepl agrees: user=> (defstruct b :foo) user=> (type b) clojure.lang.PersistentStructMap$Def user=> (type (struct b 'foo)) clojure.lang.PersistentStructMap
11:32Knekkah, better
11:33Knekkthanks
11:38mebaran151I'm still not used macros: is there a good guide online how to write them
11:39astoddardI have an absolute beginner question. Using clojure.contrib.repl-utils/source, I get a copyright message and (ns clojure.core) nil. e.g. user => (source identity). Does this mean no source is available?
11:40Chousukehm
11:40Chouserastoddard: wierd. Usually you'd see "Source not found" if that's the case.
11:41Chouser,^#'identity
11:41clojurebot{:ns #<Namespace clojure.core>, :name identity, :file "clojure/core.clj", :line 841, :arglists ([x]), :doc "Returns its argument."}
11:41Chouserastoddard: what does yours say?
11:42astoddardI get {:ns #<Namespace clojure.core>, :name identity, :file "clojure/core.clj", :line 0, :arglists ([x]), :doc "Returns its argument."}
11:42Chouserline 0 is the problem there. what version of clojure do you have?
11:43astoddardI am using the most recent clojure downloaded with the "Programming Clojure" book. Apparently Clojure 1.1.0-alpha-SNAPSHOT
11:44Chouserastoddard: link?
11:44astoddardhttp://www.pragprog.com/titles/shcloj/source_code
11:46astoddardThe repl is also started with a batch file included with the download. Is that likely a problem?
11:46Chousera batch files shouldn't hurt anything
11:47lisppaste8Anniepoo annotated #83921 "untitled" at http://paste.lisp.org/display/83921#1
11:48AnniepooI made a little GUI as a first project. I'm moving that to a new IntelliJ project to start something real
11:49Anniepoothe ns throws MethodNotFoundError for this unless I remove the :use clause
11:51Anniepooshould I not be :use ing clojure.core and clojure.contrib.seq-utils?
11:51Chousukeyou don't need to :use clojure.core
11:51Chouserno need to :use clojure.core -- that happens automatically
11:52ChouserAnniepoo: maybe paste the whole stack trace? Can't think why you'd get MethodNotFound
11:52Anniepoook, hang on
11:53Chouserastoddard: hm, I see the line 0 issue for that download of clojure as well...
11:53lisppaste8Anniepoo annotated #83921 "untitled" at http://paste.lisp.org/display/83921#2
11:54Anniepoothat's the trace after removing clojure.core
11:54ChouserI remember we were getting line 0's for a while, but I don't remember for which versions of Clojure
11:55AnniepooI'm running off the 'clojure-1.0' that downloads when you download La Clojure
11:55Anniepoobefore I was running on a direct d/l of Clojure off the website
11:56ChouserAnniepoo: you've got clojure.jar in your classpath twice
11:56Chousernot sure that's the cause of your problem, but it's not recommended.
11:56Anniepoohmm... wonder why
11:56Anniepoook, I'll figure out who'se giving it to me
11:57Chousertwo different paths
11:58ChousukeIt looks like you don't have the classes/ dir in the classpath either.
11:58astoddardChouser: I just tried using the clojure-contrib.jar downloaded with the book together with the clojure-1.0.0.jar. source works properly.
11:59Chouserastoddard: ok
11:59Chouserastoddard: you might want to email Halloway, or the google group
12:00astoddardWill do, should let them know that the book and the supplied source don't work together.
12:00astoddardThanks for the help.
12:02Anniepoothanks for spotting that. It was indeed the problem. the IntelliJ UI is confusing - there's a checkbox I'd assumed was 'I want this', it's actually 'add this to the jars'
12:04AWizzArdastoddard: how many pages does the pdf have?
12:11Anniepoowhoo hoo, small victories, extended a java class with clojure
12:12Anniepoois there an equivilent for the java import foo.mep.*; idiom?
12:13ChouserAnniepoo: no. it's exclusion is a feature. :-)
12:14AnniepooI'm aware it leads to stylistic horrors in java. But there's a style argument on the other side as well
12:15AnniepooI'm cut and pasting code to make something new, and currently there's a mass of imports
12:16Anniepoothe old code used a bunch of swing borders and weird stuff, the new probably won't
12:16Chousernot sure of the controlling argument, but I think it's been pretty well decided. One point is that there are some planned performance features that will benefit if you have a minimal set of imports
12:16Anniepooah
12:16Anniepoothat sure trumps me
12:18Anniepoomy arg would have been that, in the absence of IDE support for automatic cleanup, you tend to accumulate a bunch of 'lies' over time
12:19Chouseryeah. Maybe IDEs need to support cleanup. :-)
12:19Anniepooif I see code that imports javax.swing.* i don't assume I'm actually using EtchedBorder somewhere
12:21ChouserAnniepoo: Personally I really dislike the * -- if I don't have intimate knowledge of all the packages being * imported, I have no idea where any given classname in the code is coming from.
12:21Anniepoook, it's Sergey's fault ;c)
12:21Anniepooyes, I understand the argument
12:22ChouserI understand your argument about lies, but I guess I find it easier to do some searches when cleaning up the code to remove extra imports than to resolve non-specific imports to get my code working in the first place.
12:22Anniepoowell, having the IDE do the cleanup is the right solution
12:23Anniepoowith modern IDE's we should all be thinking more about literate programming
12:32Fossiis anybody using lancet seriously?
12:33RaynesFossi: Apparently, it's not ready for extensive use yet. So I don't think so.
12:34RaynesSomeone needs to pull Stuarts lever and get him working on it. :D
12:34Fossieither that or work on it themselves as they go ;)
12:35technomancyRaynes: we might have to wait for the 2nd edition of Programming Clojure for that
12:35RaynesIf I was more experienced with build tools, I'd extend it myself. :\
12:38technomancywell corkscrew is only 200 LOC; very easy to understand. =)
12:39Fossilancet is 139 so far
12:40technomancyoh snap!
12:40technomancywell 200 includes comments and newlines
12:40Fossi:)
12:40technomancyand it handles dependencies
12:41Fossiwhy did you start corkscrew? didn't like lancet?
12:41technomancywhich happens to be the only non-trivial part of building clojure projects
12:41technomancyFossi: stuart told me lancet was mostly for learning rather than actual use
12:41Fossiah, ok
12:42Fossiis corkscrew a wrapper over maven or such?
12:42technomancyit uses maven to resolve dependencies
12:42technomancyit can also check out dependencies from svn or git
12:43Fossiwell, if stuart has no intent to put lancet forward, maybe i should use corkscrew then
12:43technomancythe ant approach of "XML is just another programming language; wheeee!" is very disturbing
12:43Fossialthough i like ant better, but maven's dependency stuff is nice
12:43Fossiyeah, that's why i like lancet so much
12:43technomancyFossi: if you did, you would be like the fifth corkscrew user ever; so be aware it's not very polished. =)
12:44Fossikinda makes the worst part of ant better
12:44technomancywell isn't that all there is to ant though?
12:44technomancyisn't it just an engine for converting XML into action?
12:44Fossimore or less ;)
12:45technomancyto me the only interesting thing about that whole mess is the dependency system
12:45technomancy*that whole mess being Java build systems in general
12:46Fossiyeah. it really is a big mess
12:47cemerickrhickey: FWIW, the mutable locals idea you floated ~10:30 EDT sounds nifty to me.
12:55hserusi've heard ivy is a better dependency management system than maven
12:57technomancywhy's that?
12:58technomancythey use the same repository format underneath; that's all I care about.
12:58technomancybetter for building Java projects is irrelevant to me. =)
13:00hserusam trying to find a mail from a colleague comparing these two.. actually a lot of my colleagues were very vary about it
13:01hserusi've generally stuck with ant though
13:16mebaran151how would I write a macro that could pass its an argument to its expressions? I'm trying to write something that works like (with-cursor [cur] ;;exprs that use cur as though it were part of a function definition.
13:19Chousermebaran151: the normal way to do that now is with dynamic binding
13:19Chouser(binding [*cursor* my-value] ...)
13:19Chouserfunctions called from in there can use *cursor* and will get the value my-value
13:19mebaran151but binding seems like an ugly globals hack
13:20mebaran151I'd like it if they could define their own name for it
13:20Chouserit's only a global name, not a global value
13:20Chouseroh
13:20mebaran151so it would look like I just took out the fn [cur]
13:20ChouserI must not understand what you want
13:20mebaran151I had a simple defn that simply took an argument of one function and passed it the cursor
13:21mebaran151(with-cursor (fn [c] ... do stuff with the cursor)
13:21mebaran151I think it would be nice if I could do (with-cursor [c] (exprs that reference c, which will receive the cursor)
13:22Chouseroh, sure... so you just want a macro that you call like (with-cursor [c] body) which emits (with-cursor* (fn [c] body)) ?
13:23mebaran151yeah
13:23mebaran151something like that
13:23mebaran151actually
13:23mebaran151what I really need
13:24mebaran151is something that will take ([arg] a b c) and turn it into (fn [arg] a b c)
13:25Chouseryou can use #(a b c %)
13:25mebaran151how would that work with my ~exprs clause
13:26Chouserif you have a with-cursor fn that takes a single fn as an argument, you can call it like (with-cursor #(a b c %))
13:26mebaran151but would that work inside the macro that is constructing the function?
13:27Chousukethough with-cursor is really not a good name if it doesn't establish some kind of a context.
13:27Chouserif you have a macro, I don't see why you'd need #()
13:27gulagonghi there
13:27gulagongi have a little problem, and i think you can help ;)
13:27gulagongi want to create an array (create-array default-value dim1 dim2 dim3 dim4 ....)
13:27gulagongand i dont know how to make a recursive call with the rest of the dimension parameter (rest dimensions).
13:27gulagongmaybe i'm a fool but you help me anyway ;)
13:28mebaran151I guess I should call it cursor-action
13:28Chousukemebaran151: how is your cursor-action any different from a normal function that takes a single parameter, though? :/
13:28Chousergulagong: you've got a list or vector of the dimension sizes? (let [dims [10 10 10 5]] ...) ?
13:29mebaran151Chouser, I'm trying to get rid of the fn thunk
13:29gulagongi did that ...
13:29gulagongbut i want (defn create-array [default & dims] ....)
13:29Chousergulagong: ok, then maybe (apply make-array type dims)
13:29mebaran151right now as a normal defn it looks like (cursor-action [f] where f is a function of one argument that will be passed the cursor
13:30gulagongthx :)
13:30gulagongnow i see ....
13:30gulagongso simple ;)
13:30mebaran151so when I call it, it looks like (cursor-action (fn [c]))
13:30Chousermebaran151: sure, or (cursor-action #(.... % ))
13:31mebaran151I'd like to get rid of that call to fn so it would look like (cursor-action [c] (exp1) (exp2) (exp3))
13:31mebaran151I know it's not essentially
13:31mebaran151but it would be a nice bit of syntax sugar
13:31Chousukemebaran151: ah, so you want just (defmacro cursor-action-macro [c-name & body] `(cursor-action (fn [~c-name] ~@body)))
13:31mebaran151yeah
13:31mebaran151what does the @ do?
13:31Chousukethat way you can do (cursor-action-macro cursorname (do-stuff-with cursorname))
13:32mebaran151exactly
13:32Chousukemebaran151: it's the splicing unquote
13:32Chouseror (defmacro cursor-action-macro [& fn-stuff] (cons `cursor-action fn-stuff))
13:32mebaran151I see
13:32mebaran151so I'd still need my basic version
13:32mebaran151which takes a raw-fn
13:32mebaran151cursor-action-raw or something
13:32Chousermebaran151: that's the best way to do it, yes
13:32Chousukemebaran151: you don't need it, but it's easier that way
13:33Chousukemebaran151: call it cursor-action*
13:33mebaran151okay
13:33Chousukewith Chouser's version, the syntax will be (cursor-action-macro [c] stuff) which is a bit more clojurey I guess.
13:34Chousukehm.
13:34Chousukewait. it's actually missing the fn :p
13:34Chouserheh. oops.
13:35Chousersorry
13:36Chouser(defmacro cursor-action [& fn-stuff] `(cursor-action* (fn ~@fn-stuff)))
13:41Chouserslime continues to make clojure harder for people to learn
13:42Chouser"deong: Pressing “1″ is no longer necessary in recent versions of swank-clojure" ... ah, that's fantastic.
13:42Chouser(re: http://nflath.com/2009/07/initial-thoughts-on-clojure/ )
13:43Chousertechnomancy: way to go! :-)
13:43mebaran151thanks Chouser Chousuke!
13:43mebaran151that works perfectly
13:44Chousermebaran151: power to the programmer! :-)
13:48technomancyChouser: verbose stack traces are there whether you use slime or not. =(
13:48mebaran151is there a step debugger for clojure?
13:48ChousukeI have heard that java debuggers work.
13:49ChousukeI haven't tried myself :P
13:49Chousertechnomancy: yes, but slime for a long time has hidden all but the most recent "cause", which as noted in that blog sometimes leaves out important info
13:49ChouserI'd rather have too much info than not enough (though of course exactly the right amount would be better than either extreme)
13:49technomancyChouser: ah right, sure.
13:49technomancyyes, swank-clojure very much has the "my first clojure project" feel to it at times.
13:49Chouserheh
13:49technomancyworking on that one step at a time. =)
13:50drewrI wish jochu hung around here so we could chat about it
13:50drewrwe've emailed a little but that's about it
13:50technomancydimming the irrelevant lines in the traces helps a lot
13:51technomancydrewr: he's basically passed on maintenance to me
13:51technomancyanything you want to talk about? =)
13:51Chouserwhat's the logic? dim everything in the clojure namespace?
13:51drewrtechnomancy: good to know :-)
13:51drewrsounds like I need to use your fork then
13:51technomancyChouser: clojure.(lang|core), swank.*, and java.*
13:51technomancythat last one may be overzealous. =)
13:52technomancydrewr: he gave me commit rights to his, so I keep them in sync
13:52drewrgreat
13:54technomancyI guess I should look at the github network; lots of people have been hacking
13:54drewrthe only issue I'm having at the moment is the swank-clojure-find-package regexp, which I need to work on
13:55technomancydrewr: check out swank-clojure-import I just committed
13:56technomancyit prompts you for a class, then searches the classpath and adds the proper :import declaration
13:58mebaran151I would be nice if clojure had import ns.* decls
13:58mebaran151any technical reason it doesn't?
14:01Chousermebaran151: it's exclusion is a feature. :-)
14:01Chousernot sure of the controlling argument, but I think it's been pretty well decided. One point is that there are some planned performance features that will benefit if you have a minimal set of imports
14:01mebaran151ah
14:02ChouserPersonally I really dislike the * -- if I don't have intimate knowledge of all the packages being * imported, I have no idea where any given classname in the code is coming from.
14:02mebaran151the other downside though, is in an overengineered library like BerkeleyDB
14:03mebaran151import every factory, factory factory, and wrapper factory factory can get very tedious, and usually, in this case, it's very clear where the class comes from
14:03cemerickmebaran151: totally off-topic, but what do you think of BDB?
14:03mebaran151cemerick, it's pretty fast, well constructed
14:04mebaran151I'm gonna put some nice bindings up on github soon that wrap it's transactional stuff right
14:04mebaran151it's safter than TokyoCabinet (it always gets the locking right...)
14:04mebaran151I think it's a pretty good fit for serializing clojure maps, plus you could index by an arbitrary key
14:04cemerickI pinged oracle for licensing info, and got a pretty laughable response.
14:04Chousersafer or faster?
14:05mebaran151safer
14:05mebaran151not faster
14:05Chouserhm.
14:05Chouserok, thanks.
14:05mebaran151being pure java is nice
14:05mebaran151though with the way I'm designing this library, plugging in TokyoCabinet would be trivial
14:06drewrtechnomancy: fwict, it gets the ns sexp but doesn't isolate the namespace name
14:06mebaran151you just have to some how give me a cursor and database handle, and a way to open a transaction, and the rest of the code just falls into place
14:06mebaran151cemerick, BerkeleyDB is GPL no?
14:07cemerickmebaran151: not GPL, a custom copyleft license. Doesn't work for a commercial project, tho.
14:07mebaran151when I read the license, they said if you keep it on your own server, it's your own business
14:07mebaran151otherwise you have to give them the deed to your house
14:07cemerickyeah, we're redistributing/embedding
14:08mebaran151ah, it would actually be pretty good for that
14:08mebaran151were you using the C edition or the JE edition?
14:08cemerickthat's what I figured, but they're not making it easy
14:08cemerickJE
14:08Chousercemerick: maybe they'd rather you embed Oracle
14:09mebaran151tokyocabinet is actually pretty light
14:09mebaran151it might work for embedded situations
14:09cemerickChouser: it's a desktop app, of all things :-)
14:09mebaran151it's good if you don't highly multithread your app
14:09Chousercemerick: really? does "desktop app" mean a browser based app that looks like a desktop?
14:10mebaran151but under lots and threads, the TokyoCabinet really expects you to put it behind the tokyo tyrant server
14:10cemerickTokyoCabinet is *only* GPL, so that's right out. (the travails of being commercial! :-P)
14:10mebaran151only, I thought it was LGPL...
14:10cemerickChouser: nope. Desktop, netbeans platform, etc.
14:11mebaran151it's LGPL
14:11cemerickmebaran151: ah-ha, you're right
14:11mebaran151just checked the webpage
14:11cemerickhrm, I'll have to take a look
14:11mebaran151that means you can commercial use it as long you don't hide the patches?
14:11mebaran151for a server side project thought
14:11mebaran151TC likes to wedge itself
14:11mebaran151and deadlock itself
14:11cemerickhrm, that's unfortunate
14:11mebaran151and corrupt itself under high thread load
14:11mebaran151BDB hasn't had any of those problems, though it's slower
14:12cemerickLGPL is fine for redistribution. Changes have to also be LGPL.
14:12mebaran151yeah
14:12mebaran151TC is a pretty friendly license and it comes with fulltext search built-in
14:12cemerickmebaran151: doesn't sound like much of an endorsement from you, though ;-)
14:13mebaran151if you don't need to really pound it with a lot of concurrent access, it's great
14:13mebaran151see, he wrote a nifty server component for those situations
14:13technomancydrewr: huh; well I guess I don't have funky enough ns declarations to mess it up
14:13technomancylet me know what you find though
14:14cemerickhrm. I think we'd be just fine serializing all writes, actually.
14:14mebaran151Tokyo Tyrant is a class act, but I didn't want the extra deployment headache, at least righ tnow
14:14cemerickwe use couch in-house, mostly because it's so damn easy to use.
14:15technomancyit's easy to get spoiled by couch. =)
14:15cemerickone of these days, we'll get around to writing a clojure view server
14:15mebaran151the Tokyo Tyrant server api though really is a joy
14:15clojurebotthe website api refers to last release
14:15technomancycemerick: you've seen the one on github?
14:16drewrtechnomancy: meta screws it up; e.g. http://github.com/richhickey/clojure-contrib/blob/6fea921c91d453c750586c960ec92caacf4fa5e6/src/clojure/contrib/def.clj
14:16cemericktechnomancy: no -- is it danlarkin's?
14:16technomancycemerick: no, it's called clutch iirc
14:17technomancydrewr: the other way to solve that would be to make ns support docstrings. =)
14:17technomancythough I guess we'd still need to update swank for that
14:17drewrtru dat
14:18cemericktechnomancy: thank you for the tip!
14:19technomancycemerick: well, I haven't actually _used_ it. =)
14:19technomancyworth knowing about though.
14:19Chousermebaran151: which version of TC are you talking about?
14:19cemericktechnomancy: definitely worth a look. We're deep into swing of all things right now, but that should change next month.
14:23Lau_of_DKVery big problem: We have a clojure project at work, which we have been building for quite some time. In essense it traffics data between ftp sites and parses/interprets the data. This project was moved into the testing fase today. In doing that we changed the adresses from local ftp sites to external ones. When we started a REPL and loaded the code = No problems, then we ran it = Exception thrown. Then I manually evaluted the function that was t
14:25ChouserLau_of_DK: that cut off at "evaluted the function that was t"...
14:25Lau_of_DKThen I manually evaluted the function that was throwing the error, without changing any code, then whole program executed flawlessly. What could be the cause of this?
14:25hiredmanLau_of_DK: my quick fix for networking stuff is always to pass -Djava.net.preferIPv4Stack=true to java, dunno if that will help you
14:26hiredmanLau_of_DK: is this all on the exact same jdk?
14:26Lau_of_DKYep - Same system, same jdk, same everything
14:26Chouserwhat exception?
14:27krumholtare you using namespaces? did evaluating the function in a different namespace change something?
14:27cemerickoh, TC doesn't build on windows. There's a fork, but, ugh.
14:27Lau_of_DKIt was the sftp function which runs "ls" on the remote server which returned "No such file" - This should not (and have never) occur when the directory is non existant or empty
14:27Lau_of_DKkrumholt: Yes - Evaluating it in the same namespace fixes the problem, so we didnt try in others
14:28krumholtLau_of_DK, are you using comparison of symbols? not exactly sure if that could cause the problem
14:29Lau_of_DKNot to my knowledge
14:30krumholtis it possible have a look at the function that caused the problem?
14:31Lau_of_DKsec
14:31Lau_of_DKI have to switch to vpn
14:31hiredmanLau_of_DK: is this always running against the same ftp daemon?
14:33hiredmanI've never rolled an ftp client myself, but I hear the protocol has a lot of leeway so maybe you are running into a slight difference in behaviour somewhere
14:33Lau_of_DKhiredman: Yes
14:34Lau_of_DKStill there?
14:34hiredman~ping
14:34clojurebotPONG!
14:34Lau_of_DKhiredman: How would that account for code not working on first evaluation, and then working again on the second?
14:34Lau_of_DK(defn download-messages
14:34Lau_of_DK []
14:34Lau_of_DK (with-sftp-connection c
14:34Lau_of_DK (let [files (debug "Retrieving list of messages" "OK" (get-messages c))
14:34Lau_of_DK edifacts (map #(debug (str "Downloading: " %) "OK"
14:34Lau_of_DK (download-message c %)) files)]
14:34Lau_of_DK files)))
14:34Lau_of_DKThis is the bit that breaks down
14:35Chousukehm
14:35Lau_of_DKAnd the part that fails is (debug "Retrieving...") which is a macro that works exactly like Time.
14:35hiredmanerm
14:36Chousukelaziness issue? :P
14:36Lau_of_DKIf I then manually execute the body (get-messages c) then it works
14:36hiredmanyeah, nothing is forcing the map
14:36Lau_of_DKI tried it in a doseq, that didnt make a difference, its not the map thats dying
14:39Chouserunless you specifically want edifacts to be lazy, I'd stick a (doall ...) around it just to be sure
14:40Lau_of_DKI agree, and thats done in other parts, but thats not the problem right now, its the (get-messages c) thats failing, so any input why that might be? And why a second evaluation then fixes it ?
14:41ChousukeIt would be useful to see the debug macro, and the get-messages function :P
14:41krumholtLau_of_DK, i am assuming debug is just loging something and then evaluating (get-messages c) ?
14:41Lau_of_DKkrumholt: yep, debug is exactly like the time macro in core
14:41Chouserdid you paste the exception somehwere?
14:41Lau_of_DK(defn get-messages
14:41Lau_of_DK [channel]
14:41Lau_of_DK (doall
14:41Lau_of_DK (for [line (.ls channel (str edi/*remote-read-path* '* edi/*ext*))]
14:41Lau_of_DK (.getFilename line))))
14:41Lau_of_DKNo, I just told you what it said - I dont have it here
14:42cschreinerHello all
14:43cschreinerI have a question regarding debugging clojure inside emacs using slime. How do you do it?
14:44hiredmanLau_of_DK: so get-messages is throwing the exception?
14:44Lau_of_DKAs I recall
14:45krumholt_Lau_of_DK, is edi your namespace?
14:45ChouserLau_of_DK: if at all possible, I'd recommend getting the actual stack trace -- can be quite valuable as a debugging aid.
14:45Lau_of_DKYep
14:45Lau_of_DKChouser, I'll dig it up
14:45Chousukeany chance get-messages is getting evaluated twice?
14:46Lau_of_DKChousuke: What are you thinking?
14:47Chousukewell, a macro is involved
14:47Lau_of_DKNo, there's not chance
14:49Chousukethen my last remaining guess is that you're passing in an invalid connection or something
14:52Lau_of_DKNo it connects just fine
14:52Lau_of_DKthe log says "Connecting" "Connected" "Retrieving list of files", and then it borks
14:52Lau_of_DKor rather, hangs there
14:53krumholt_Lau_of_DK, for me it sounds namespace related why not (str edi/*remote-read-path* "*" edi/*ext*) instead of (str edi/*remote-read-path* '* edi/*ext*) ? i don't really know if that can be wrong
14:55mebaran151cemerick, one thing I just noticed glancing at the TokyoCabinet docs again
14:55mebaran151the iterator is not thread safe global, which is probably why I experienced so many issues
14:55mebaran151if you lock on that, everything work out
14:56hiredmanLau_of_DK: NPE?
14:58hiredmanI would add a (prn line) before the (.getFilename line)
14:58Lau_of_DKChouser: I cant get that stack-trace, because the systems are hardcoded to accept certain IPs, mines not one of them, so I'm only getting "Auth fail"
14:58Lau_of_DKBut I just dont understand the logic - How can you evaluate a function and have it fail, then evaluate the exact same code, and have it run fine ?
14:58hiredmanor even (prn (class line))
14:58hiredmanwell obviously something is not the same
14:59ChouserLau_of_DK: lots of ways: different dynamic bindings, different threads, different lazy realizations
15:02cemerickmebaran151: after looking at it for a bit, my biggest initial issue is the lack of windows support in the official codebase
15:03cemerickhaving full-text indexing builtin is pretty compelling, though. I may give the windows-compatible fork a roll.
15:05angermanis there a default approach to create a drawable area with clojure?
15:05hiredmanuh
15:05hiredmanjust use swing?
15:05angermanI'd like some kind of a panel on which I can draw and use the repl to interactibly play with it.
15:06hiredmanclojurebot: swing?
15:06clojurebotPardon?
15:06hiredmanclojurebot: swing is <reply>http://java.sun.com/docs/books/tutorial/uiswing/
15:06clojurebotAck. Ack.
15:06angermanhiredman: so like creating a JFrame adding a JPanel and owerwriting it's draw-something method with a global Graphics2d element?
15:06hiredmanclojurebot: swing?
15:06clojurebothttp://java.sun.com/docs/books/tutorial/uiswing/
15:07hiredmanangerman: sure
15:07cemerickangerman: there's also processing (with the clj-processing wrapper), which is very pleasant
15:09angermancemerick: well I basically just need stuff like drawing lines. And I have no experience with processing
15:11mebaran151cemerick, that fork is so broken
15:11mebaran151that was one of the reasons we switched: I have a dev on windows and it made him cry
15:11cemerickoh, bummer
15:11mebaran151that fork is unspeakably broken
15:12cemerickI guess I'll stop reading about all the greatness of TC
15:12mebaran151and compiling it was insane
15:12angermanTC?
15:12cemerickI've long wanted to have FTI baked into an embedded DB, but I've never seen a good impl.
15:12mebaran151if you need something like a key value store
15:12cemerickangerman: Tokyo Cabinet
15:12mebaran151qdbm might do it for you
15:12angermanthough that
15:12angermanjust got it working yesterday
15:13angermanand played a bit with the tabledb
15:13cemerickwell, I presume that qdbm is essentially legacy, given TC
15:13angermanqdbm?
15:14angermanbut yes. Compiliing TC on OS X was insanely stupid. Especially as I wanted a different prefix and OS X Java 1.6 is 64bit
15:14cemerickangerman: http://www.google.com/search?q=QDBM
15:15angermancemerick: yes probably
15:19mebaran151qdbm is windows okay
15:20angermanhttp://gist.github.com/151535
15:20angermanif anyone's interested on installing TC on os x
15:23mebaran151ports are your friend
15:25angermanmebaran151: sometimes :)
15:26mebaran151oh you mean to get java to work
15:26angermanmebaran151: well. ports are fine as long as you follow the ports setup
15:27mebaran151java on Mac OS X is mostly a mess anyway
15:28angermanwell ...
15:28mebaran151cemerick, I've actually had qdbm work with ruby bindings before on windows
15:28mebaran151so if you don't need super performance, it's probably sufficient
15:42rapidoanyone interested in a immutable btree implementation? (to replace tokyo cabinet and to be in line with the clojure spirit)
15:48mebaran151rapido, that persists to disk?
15:48mebaran151disk persistence is tricky
15:49rapidomebaran151: yes, to disk, like berkeleydb
15:50rapidomebaran151: but much simpler, because of immutability and append-only properties.
15:50hiredmanI think using an agent+watcher would work pretty well
15:51rapidohiredman: my btree implementation has another interesting property: it is canonical
15:52mebaran151rapido, really?
15:52rapidothe order of insertions doesn't matter: it will always create the same tree
15:52mebaran151but often in the life of an app, you may have to delete something, else your data becomes explosive
15:53mebaran151is there a way to prune older versions (it would be great to have a btree that at any given time you could access its state from the last n places)
15:53rapidomebaran151: you can always 'garbage collect' - you just have to explicitly state which trees are 'root' (reachable) and garbage collect
15:54mebaran151ah, that would actually be pretty neat
15:54mebaran151but wouldn't garbage collection involve rebuilding the whole tree, or would it be a simpler op than that?
15:55rhickeyrapido: sure, where is it?
15:56mebaran151also berkeleydb has pretty good memory caching builtin
15:57rapidorhickey: i just finished version 0.1 (in java) and it is a little bit rough around the edges
15:58rapidorhickey: i'm still experimenting with different page-sizes.
15:59rapidocurrently, what works is that i make the bottom nodes the fattest (4k) and the top nodes the leanest (binary node)
16:00rapidothis scheme works because when you 'mutate' a immutable tree, a lot of top nodes are created, while the bottom nodes pretty much stay as they are
16:02rapidobut the property that they are canonical brings additional savings.
16:02rapidoyou can do O(1) equality checks (probabilistically)
16:04rapidoi guess i have to write a small paper to explain the workings - and then release the code.
16:05rhickeyrapido: sounds neat - let us know when we can try it
16:07rapidosure, i'll let you know - i think this stuff fits clojure like a glove.
16:32ericthorsenAnyone know what clojure.core/import* is? I see this in the import macro in the latest core.clj ... wondering if this is a typo?
16:34Chouserericthorsen: import used to be a function, I believe, and is now a macro that calls import*
16:34Chouserhm
16:34hiredmanericthorsen: a lot of things that are "special forms" are really macros that use something even more primitive, the more primitive form has the same name but suffixed with a *
16:35ericthorsenChouser: ok...I may just have some build problems...
16:35Chouseryeah, scratch that. import was a special form and is now a macro
16:35AnniepooI've got a fragment of a paintComponent method (.fillRect g (.getBounds this))
16:35ataggartanyone know if we get some kind of notification once our CA has been received?
16:36Anniepoothis is a bug because, oops, fillRect takes 4 args, x,y,w,h
16:36Chouserataggart: your name should eventually show up on http://clojure.org/contributing
16:36Chouserataggart: looks like you're there
16:36ericthorsenChouser: I found it in Compiler.java...my jars must be out of sync???
16:36ataggartaha! excellent, thanks
16:37Chouserericthorsen: could be -- clean and rebuild?
16:37hiredmanAnniepoo: ?
16:37ericthorsenChouser: yup...I'm playing with your clojure-compiler
16:37Chouserericthorsen: oh! my.
16:37hiredmanChouser: look what you did!
16:37Anniepoois there some idiomatic way to fix this? I see a few ways to do it, but wonder if there's an idiom since
16:37Chouserericthorsen: it's not really ready for that...
16:38Anniepoothe fix feels clunky
16:38hiredmanAnniepoo: which fix?
16:38ericthorsenChouser: Well, I was doing some code analysis for the enclojure plugin and saw that you did so much more already...I was hoping I could use some of that work
16:39Chouserah. well, perhaps then. Just don't expect it to, you know, compile anything. :-)
16:39Chouserericthorsen: did you consider using Clojure's own Compiler.analyze?
16:39Anniepoowell, in this case the x,y,w,h have individual accessors, I could call them, or I could do the .getBounds once into a let variable
16:39ericthorsenChouser: I just need to analyze part for now
16:40Anniepoojust wondering what's more idiomatic
16:40ChouserAnniepoo: if a method returns an object the other method simply can't accept, you've run into an ugly little corner of the Java API
16:41hiredmanAnniepoo: I imagine most idiomatic would be to wrap the call to .fillRect in a multifn
16:41Anniepooand wanting some (bar (foo .getBlah .getMep .getGort))
16:41Anniepoothat is the same as (bar (.getBlah foo) (.getMep foo) (.getGort foo))
16:41hiredmanthat takes either X or x y z w
16:42Chouser(bean obj) ?
16:43hiredman(defn fill-rect ([g this] (let [foo (.getBounds this)] (fill-rect g (.getX foo) (.getY foo) (.getWidth foo) (.getHeight foo)))) ([g x y w h] (.fillRect g x y w h)))
16:43hiredmansomething like that
16:44Anniepooyah
16:44Chouser(map (partial get (bean obj)) [:x :y :w :h])
16:45Anniepoowhat's bean?
16:45Chouser,(doc bean)
16:45clojurebot"([x]); Takes a Java object and returns a read-only implementation of the map abstraction based upon its JavaBean properties."
16:45Anniepoochouser, you're on the right track here
16:45kotarakThere are functions I really never use.... That's scary. I probably miss a lot...
16:46Chouserhm... but if you're then passing to a method you can't use apply anyway, so ...
16:47Anniepooah, ok
16:47Chouserericthorsen: clojure.contrib.repl-utils/expression-info uses Compiler.java to analyze a Clojure expression. That's more likely to be correct than anything in clojure-compiler
16:47technomancythat definition of bean is not very helpful for people who have never heard of a JavaBean
16:48Anniepoomuch happier with all the suckiness moved off onto Java
16:48Chouser,(bean 5)
16:48clojurebot{:class java.lang.Integer}
16:48ericthorsenChouser: I'll take a look at that.
16:48Anniepoome wishes I'd never heard of a javabean
16:49Chouser,(.invoke (first (filter #(= (.getName %) (str "intern")) (.getMethods clojure.lang.Var))) clojure.lang.Var (to-array [*ns* 'expression-info (fn [expr] (let [fn-ast (clojure.lang.Compiler/analyze clojure.lang.Compiler$C/EXPRESSION `(fn [] ~expr)) expr-ast (.body (first (.methods fn-ast)))] (when (.hasJavaClass expr-ast) {:class (.getJavaClass expr-ast) :primitive? (.isPrimitive (.getJavaClass expr-ast))})))]))
16:49clojurebot#'sandbox/expression-info
16:49Chouseroops sorry
16:49Chouser,(expression-info '(let [x 5] x))
16:49clojurebot{:class java.lang.Integer, :primitive? false}
16:50Chouserhiredman: that was honestly an accident -- meant to paste to another window. sorry!
16:51hiredman*shrug*
16:51hiredmanI wouldn't have noticed if you didn't saying anything
16:51Chousukewait, what
16:51hiredmanthat is gnarly looking
16:51hiredmanChouser: shhhh
16:51clojurebotWho??
16:51hiredmanwhat??
16:52hiredmanI meant Chousuke there
16:53ChousukeThat just demonstrates that a blacklist is never enough :P
16:54mebaran151is it possible to define a multimethod that has a possible if it is fired without any arguments
16:54Chouserwho needs special forms?
16:54Chousermebaran151: yep
16:54mebaran151oh how?
16:54hiredmanwhat?
16:54mebaran151sorry for the typo'ing
16:55hiredmanI did not actually understand that
16:55mebaran151a multimethod that has an action when called without arguments
16:55hiredmanbut I guess Chouser did
16:55hiredmanoh, sure
16:55mebaran151I gotta pay attention to my edits more
16:55Chousukemebaran151: just have the dispatch function accept any number of arguments
16:55Chousukethen return some value for the no-args case
16:55Chouser(defmulti foo (fn [& args] (if args (type (first args)) :no-args)))
16:56Chouser(defmethod foo :no-args [] "none")
16:56Chouseror something
16:56kotarak(defmulti foo (fn [& args] (if (zero? (count args)) :zero :bla))) (defmethod foo :zero [] ...)
16:58mebaran151thanks all
16:59hiredman((comp type first list) 1 2 3)
16:59hiredman,((comp type first list) 1 2 3)
16:59clojurebotjava.lang.Integer
16:59hiredman,((comp type first list))
16:59clojurebotnil
16:59technomancydid they ever fix the tarbomb for the release?
17:03angermanhow would i compute a number in [0,1] into a base4 or base9 number? best would be to be able to access the digets seperatly
17:05angermanconverting 1/8 should in base 4 should be something like '(0 2)
17:05ataggart,(Integer/parseInt "110" 2)
17:05clojurebot6
17:06ataggart,(Integer/toString *1 4)
17:06clojurebotjava.lang.IllegalStateException: Var clojure.core/*1 is unbound.
17:06ataggart,(Integer/toString 6 4)
17:06clojurebot"12"
17:07hiredmanhttp://blogs.azulsystems.com/cliff/2009/07/javaone-slides.html <-- slides from Cliff's javaone presentations
17:07angerman,(Double/toString 0.5 4)
17:07clojurebotjava.lang.IllegalArgumentException: No matching method: toString
17:08ataggartonly integral types support a radix
17:08angermanhm.
17:08angermanwell I know how the alogrithm works. it's basically like take number x multiply by base, take int part and continue with fraction part
17:08angermanit can go to infinity though :/
17:09angermanlike 1/3. -> 0.11111...
17:12Chousersounds like a nice place to use a lazy seq
17:12angermanyes that's probably the best approach. I'm just too new to clojure to get that implemented :/
17:14Chouserthe input is a fraction in base 10 and the output should be a seq of digits, each less than base?
17:14angermanChouser: yes.
17:15angermanso basically (def to-base [base frac] ...)
17:16angerman(let [t (* base frac] (int-part t) (to-base base (frac-part frac)))
17:16angermansomething like that.
17:17hiredman"Each conversion passes all data thru cache"
17:17hiredman:(
17:18Chouser(defn radix-seq [base frac] (lazy-seq (cons (rem (int frac) base) (radix-seq base (* base frac)))))
17:18Chousernot at all sure that's right
17:18Chousernote it always generates a infinite seq, so be careful printing it
17:20angermanChouser: how would I take the first n elemts of it?
17:20Chouser(take n (radix-seq 4 1/3))
17:21angermanok, now comes the interesting part
17:21angermanI have four functions H0, H1, H2 and H3
17:22angermanso if I have (1 1 1 1 1) I'd like them to get (H1 (H1 (H1 (H1 (H1 '(0 0))))))
17:23angermanso I guess I'd have to have a map of {0: H0, 1: H1, 2:H2, 3: H3} and then have the somewho applied to the sequence.
17:24Chouser(apply compose (map [H0 H1 H2 H3] [1 1 1 1 1]))
17:24Chouser((apply compose (map [H0 H1 H2 H3] [1 1 1 1 1])) '(0 0)) ; I guess
17:25angermanChouser: hmm. does that translate 0 to H0 and 1 to H1?
17:25Chouser,(map [:h0 :h1 :h2] [0 1 0 2])
17:25clojurebot(:h0 :h1 :h0 :h2)
17:25angermannice
17:26Chousersorry
17:26Chousercomp
17:26Chousukecomp
17:27angermanwow, this is awesome
17:27angermanI seriously need to learn more clojure
17:27angermanok, so what was this all about.
17:27angermanI'm trying to do the mapping into a room-filling-curve (? engl)
17:28angermanmapping [0,1] -> [0,1]^2
17:28technomancybecause they're so awesome
17:28ChouserI never use them.
17:28Chouserexcept to solve others' problems.
17:29Chousermy problems all seem to be about java interop
17:30technomancy=(
17:32jbondesonevery problem i have with clojure-java interop i remember how painful .net-com interop is.
17:32jbondesonand then it just doesn't seem so bad
17:33technomancyoh totally. also sometimes it also helps to remember a time when you were kicked in the crotch.
17:33technomancy(depending on the Java library)
17:33Chouseroh, it's not bad, it's just not (apply compose (map ...)) :-)
17:34Chouserand beating on Java apis at a REPL with some custom macros at hand is pretty amazing
17:36angermanhmm ok, so I do have a canvas to draw on. and it seems to draw at least a little bit corretly
17:37angermanhow do I generate samples in [0,1] e.g. 100 evenly spaced?
17:37technomancyangerman: are you using processing for this?
17:38Chouser(range 0 1 0.01) ?
17:38Chouserooh, or (range 0 1 1/100)
17:38angermantechnomancy: no. A JPanel hooked into a JFrame redrawing using a Buffered Image
17:38jbondesonyeah, the second will give you the exact, first one will have rounding fun
17:40angermangna...
17:40rhickeyaargh - how/where do I alter Clojure's build.xml to get a build-time .jar dependency?
17:41angermanfor drawPolyline I need my [(x1 y1) (x2 y2) ....] to be in the form [x1 x2 ...] [y1 y2 ...] length
17:44jbondesonrhickey: are you trying to have it pick up a jar path from the command line?
17:44Chousercontrib depends on clojure -- could check it's ant xml
17:45rhickeyjbondeson: whatever it takes
17:45angermanhow do I round a float to the next int?
17:45angermanwell round a fraction
17:45notostracaceil?
17:46angermanwell ceil and floor do no rounding .
17:46jbondesonrhickey: is this going into the compile-clojure or compile-java nodes?
17:47jbondesoni know how to get a new classpath into the java node, but haven't done anything with the javac nodes
17:47rhickeycompile-java
17:47kotarakangerman: wild guess: Math/round?
17:47angermankotarak: not found ;/
17:47angermanhmm...
17:47jbondesonyou can promote the classpath property to a node and add path nodes
17:47jbondesonlet me throw one up on a paste
17:49lisppaste8jbondeson pasted "ant classpath" at http://paste.lisp.org/display/83954
17:49jbondesonthat's from one of my build.xml files
17:49jbondesoni'm by no means an ant expert
17:49jbondesonbut that's how i've been throwing in new jars to the classpath at build
17:49ataggartthere are about a half-dozen ways to do it. More detail might help.
17:50rhickeyok, got the jar found, now: class file has wrong version 50.0, should be 49.0
17:51rhickeyworking now, thanks
17:53notostracaangerman: http://code.google.com/p/clojure-contrib/source/browse/trunk/src/clojure/contrib/math.clj
18:04ataggartalternately: http://github.com/richhickey/clojure-contrib/blob/6fea921c91d453c750586c960ec92caacf4fa5e6/src/clojure/contrib/math.clj
18:07hiredman~def expt
18:07hiredmanugh
19:02mebaran151 I'd like to model my bdb bindings as a giant lazy hash
19:02mebaran151however, I haven't figured out a good way to handle managing cursor resources
19:03hiredmanmebaran151: put a {} in an agent and add a watcher
19:05AnniepooYikes! I'm writing this little desktop GUI editor for work. I'm halfway done with it and just noticed that the basic problem it's supposed to solve is the knapsack problem
19:09mebaran151hiredman, oh you mean to put the key back right when somebody asks for it
19:09mebaran151*the cursor back
19:09mebaran151but then the disk has to seek all over again
19:10hiredmanI am not actually thinking about the cursor
19:31mebaran151I had a simple implementation based on that exact idea, with a watch coming in behind the scenes to put the cursor in
19:31mebaran151but I slowly ran out of cursors because they weren't being closer
19:31mebaran151*closed
19:32technomancyis there anything like agent-local bindings?
19:34technomancyI want to wrap everything that an agent executes in a single binding call
19:34dreishSo what's this thing I keep seeing on the twitters about Sunn O))) and rhickey?
19:35technomancydreish: I can't figure that out.
19:37technomancydreish: I think it's spam-bots re-tweeting things they suspect may be popular
19:37dreishtechnomancy: That was my best guess as well.
19:37technomancybut it has a very poor algorithm for determining how to get clicks
19:38dreishNot sure I'm reading this correctly, but it looks to me like Agent.java has to go out of its way a bit to recreate the bindings of the thread that sent the action. There's probably room to do something like per-agent bindings, but I don't see it implemented already.
19:38technomancyis there any way to get something like the current thread ID?
19:39technomancyI could just look up a value in a map
19:39technomancyI guess Thread/currentThread ?
19:40dreishYeah, (.getId (Thread/currentThread))
19:41technomancyor just the thread itself if it's a map ke
19:41technomancyy
19:41dreishLooks like the ID is unique among all threads that ever were.
19:42dreishI have a repl that evals everything in a thread so it can be backgrounded if it takes too long, and each time I call the above, I get a different ID.
20:10RaynesHoney, I'm home.
21:52ericthorsenChouser: (analyze (read-string "(ns ns.test (import (java.lang String)))"))
21:53ericthorsenChouser: is giving me...java.lang.RuntimeException: java.lang.Exception: Unable to resolve symbol 'clojure.core/import*'
21:53ericthorsenChouser: I'm using the latest of all
21:56durka42ericthorsen: shouldn't that be :import
21:56ericthorsendurka42: Yes...a typo on my paste..
21:56ericthorsen(analyze (read-string "(ns ns.test (:import (java.lang String)))"))
21:58durka42(doc analyze)
21:58clojurebot"/;nil; "
21:58durka42i get cannot find symbol analyze :)
21:58durka42where is it
21:59hiredman~def c.l.Compiler
21:59ericthorsendurka42: sorry...it's in Chouser's net.n01se.clojure-compiler project
22:00durka42(doc reductions)
22:00clojurebot"clojure.contrib.seq-utils/reductions;[[f coll] [f init coll]]; Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."
22:01durka42,(reductions (fn [sum nextpair] (prn 'schedule sum) [(+ (first sum) (first nextpair)) (second sum)]) '[1 a] '[[2 b] [3 c] [4 d]])
22:01clojurebotjava.lang.Exception: Unable to resolve symbol: reductions in this context
22:01durka42(use 'clojure.contrib.seq-utils)
22:01durka42,(use 'clojure.contrib.seq-utils)
22:01clojurebotnil
22:01durka42,(reductions (fn [sum nextpair] (prn 'schedule sum) [(+ (first sum) (first nextpair)) (second sum)]) '[1 a] '[[2 b] [3 c] [4 d]])
22:01clojurebot([1 a] [3 a] [6 a] [10 a])
22:01durka42^ am i reinventing the wheel here?
22:05hiredman,(take-while identity (iterate rest '([1 a] [2 b] [3 c] [4 d])))
22:05clojurebotExecution Timed Out
22:05hiredmanwhoops
22:06hiredmanno, I don't think you are reiventing the wheel
22:11durka42,(reductions (fn [sum nextpair] [(+ (first sum) (first nextpair)) (second nextpair)]) '[1 a] '[[2 b] [3 c] [4 d]])
22:11clojurebot([1 a] [3 b] [6 c] [10 d])
22:11durka42that's better
22:11durka42but i implemented it with recursion instead
22:13hiredmanI think you could do it with reduce
22:13durka42reduce gets me [10 d]
22:15hiredman,(reduce #(conj %1 (first (pop %1))) [] [[1 :a] [2 :b] [3 :c]])
22:15clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--3134$fn
22:15hiredmananyway
22:15hiredmansomething along those lines
22:15hiredmanpeek
22:15hiredmanI think, not pop
22:16hiredman,(reduce #(conj %1 (+ (last %2) (first (pop %1)))) [] [[1 :a] [2 :b] [3 :c]])
22:16clojurebotjava.lang.IllegalStateException: Can't pop empty vector
22:16durka42,(reduce (fn [as b] (conj as [(+ (ffirst as) (first b)) (second b)])) '[[1 a] [2 b] [3 c] [4 d]])
22:16clojurebotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer
22:16durka42,(reduce (fn [as b] (conj as [(+ (ffirst as) (first b)) (second b)])) [] '[[1 a] [2 b] [3 c] [4 d]])
22:16clojurebotjava.lang.NullPointerException
22:16durka42fail
22:17hiredman,(reduce #(conj %1 (+ (last %2) (first (pop %1)))) [[nil 0]] [[1 :a] [2 :b] [3 :c]])
22:17clojurebotjava.lang.NullPointerException
22:17hiredmanbah
22:19durka42((fn [a b & cs] (prn a b) (if cs (recur (+ a (first cs)) (second cs) (nnext cs)))) 1 :a, 2 :b, 3 :c, 4 :d)
22:19durka42,((fn [a b & cs] (prn a b) (if cs (recur (+ a (first cs)) (second cs) (nnext cs)))) 1 :a, 2 :b, 3 :c, 4 :d)
22:19clojurebot1 :a 3 :b 6 :c 10 :d
22:58Chouserericthorsen: clojure-compiler is probably just out of date. Haven't touched it in a while.
23:30yangsxMy program prints this message: Exception in thread "Call-on-write Stream" java.lang.RuntimeException: java.lang.StringIndexOutOfBoundsException: String index out of range: 56
23:31yangsxI guess it's caused by the Java library I'm using
23:32yangsxXOM java XML library
23:34yangsxVery strange: run the function again and it does not print such error message any more.
23:35yangsxand gives me the same result
23:35hiredmanwhere is the full stracktrace + code?
23:35yangsxNo stacktrace at all.
23:35hiredman(.printStracktrace *e)
23:35hiredmanStack
23:36yangsxI mean not the usual stack trace with slime
23:36hiredman*shrug*
23:36hiredmanthat is not a lot of information to debug from
23:39lisppaste8yangsx pasted "strange Exception" at http://paste.lisp.org/display/83979
23:39yangsxhiredman: yeah, I'm puzzled, too. The printed stacktrace seems not so helpful.
23:42hiredmanI imagine it is slime stepping in and being "helpful"
23:43hiredmanwell, decompose, re-think, add calls to prn