#clojure log - Jul 31 2008

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

0:20 dkf: did the syntax change so that (defn *thing* (ref [])) no longer works?

0:20 cause I'm getting an Don't know how to create ISeq from: Symbol exception

0:35 hmm, I guess that should have been a def

1:07 I have a vector, [1 0 1 0], in *myRef .. (seq @*myRef*) and (vec @*myRef*) always return the vector within another set of brackets.. how do I get rid of those brackets, so that conjing another vector (or mutation thereof) is seen as just one list of vectors (and no more levels deep)

5:01 meredydd: Chouser: Thanks for that - loadResourceScript is something I was entirely unaware of!

7:03 Hmm, another compiler bug

7:04 Unfortunately, I'm not quite sure how to reproduce this...seems to be an interaction of a couple of macros

7:21 rhickey: *prod*

7:22 rhickey: I've managed to reduce it to one line, to the point where removing any of the forms causes it to start working again

7:22 (def k) (. k dosomething (do (try :something (catch java.lang.Exception e :something-else )) nil))

8:42 Chouser: meredydd: I can confirm that error

8:43 dkf: (conj @*myRef* 2) ==> [1 0 1 0 2]

10:15 rhickey: meredydd: looking at your verify error now

10:15 meredydd: ta

10:16 * rhickey hates Java's statement/expression dichotomy

10:16 cemerick: looks like clojure-contrib/import-static hasn't been updated to the new namespace scheme (there's references like set/intersection, rather than clojure.set/intersection) -- is this right, or am I missing something?

10:20 Chouser: cemerick: I think you're right. Tossing in a (alias 'set 'clojure.set) seems to fix it right up.

10:20 cemerick: Chouser: yeah; although, it should also be in an import_static dir, yes?

10:22 Chouser: oh, sure enough. looks like most of contrib hasn't been moved yet.

10:23 but a bunch of stuff has been copied!? hm.

10:23 looks like a bit of a mess at the moment.

10:24 cemerick: Chouser: yeah, I saw that; I was thinking that perhaps the top-level files are there to continue support for those who are following contrib but not clojure head (and therefore aren't using the new namespaces, etc)

10:25 Chouser: yeah, you must be right. I guess I should update my contribs.

10:25 dkf: chouser: I was looking for turning [1 0 1 0 1] into [1 0 1 0 1][1 0 1 0 2] so, basically, i'm derefing an element, mutating it, then conjing it on. My problem was that (seq @*myRef*) returns ([1 0 1 0 1]) and not [1 0 1 0 1]

10:26 but I ended up using (last @*myRef*)

10:26 Chouser: what is [1 0 1 0 1][1 0 1 0 2] ? If it's two things they must be in some kind of container?

10:26 dkf: a vector

10:27 *myRef* is []

10:27 so it's [[1 0 1 0 1][1 0 1 0 1]]

10:27 Chouser: ah, ok.

10:27 cemerick: Chouser: although, the top-level lib.clj has a (alias 'set 'clojure.set) in it, which wouldn't work prior to the new namespace stuff (I think -- don't remember which order alias and new namespaces went in)

10:28 dkf: fun little project.. I'm gonna need some more help here in a bit. I'm making a 2d cellular automaton, ala wolfram

10:30 right now, though, because I'm such a novice functional programmer (or even programmer, for that matter), I'm accomplishing it through what I like to call "brute force programming".. where there's no recursion.. it almost looks like assembly :)

10:30 So my next step is to condense it down to recursive structures.

10:32 Chouser: dkf: sounds like a good approach. I'm always in favor of making it work at least a little before making it right or pretty.

10:32 rhickey: dfk: as a tip, keep the ref logic out of the main logic - don't use refs/@ in the functions that calculate new state

10:34 dkf: right.. I spent half a day thinking about how I was going to clojure-ify this problem.. then said screw it, I'm building each instruction

10:34 rhickey: (alter ca-ref ca-step)

10:35 lisppaste8: dkf pasted "automaton" at http://paste.lisp.org/display/64480

10:35 dkf: there it is

10:36 I'm not sure if that's how I'll actually use it. I might just have one vector and through away the trailing subvectors

10:37 rhickey: dkf: first thing to try is vector equality, getting rid of the nths: (= v [0 0 0])

10:38 dkf: ah.. of course!

10:40 rhickey: dkf: could probably turn tri-iterate into a one-liner with rem and no cond

10:40 dkf: wait a minute. which function are you talking about?

10:41 rhickey: dkf: rule45

10:41 cemerick: Chouser: are you making any changes in clojure-contrib to bring it up to speed? If not, I'll post a msg on the group to see where people see things going there.

10:41 Chouser: cemerick: go ahead and post. I haven't been paying close enough attention to be sure what needs to be changed.

10:42 dkf: ah, i see

10:42 cemerick: Neither have I really (short of those pieces that I use already).

10:42 dkf: rhickey: how would you use rem in tri-iterate?

10:44 rhickey: dkf: the logic in each branch of the cond is the same relative to n

10:46 dkf: right, but remainder.. how does dividing return 3 elements from a given portion of the vector?

10:47 Chouser: you can use remainder to calculate the index.

10:47 rhickey: rem is used when you have wrap-around logic

10:47 dkf: my math isn't so good.

10:47 Chouser: (rem (+ n 5) 6) to decrement n wrapping around at 6

10:50 dkf: the repl says you're right

10:50 oh, i see

10:51 Chouser: right, so you can use the same kind of pattern to increment wrapping around as well

10:52 dkf: ah, but wait.. (rem (+ 6 5) 6) --> 5 .. (rem (+ 0 5) 6) --> 5

10:53 Chouser: oh, you're right. you found a bug in my code. :-)

10:53 dkf: need to get that sixth element

10:53 but I see what you're saying

10:53 Chouser: since you actually have 7 values (including 0 and 6) you want the remainder when dividing by 7 (not 6 like I said)

10:53 dkf: ah, ok

10:55 so it's (rem (+ n 6) 7)

10:55 I've never seen that use of remainder before

10:58 great. So with this, I will be able to make automatons of any size

10:59 rhickey: dkf: right!

10:59 dkf: That was next on my todo list :)

11:05 rhickey: dkf: there's also a nice way to do it with partition, cycle and range, when you are ready for the next level

11:12 cemerick: apropos of nothing -- while reorganizing a project here to be in step with the new namespace system, I'm finding this one-directory-per-namespace standard very tiresome. It seems like supporting one file-per-namespace as well as the directory-per-namespace (for namespaces that required multiple source files) would be far friendlier. I don't know what that would require in lib or what the ramifications would be elsewhere, of course.

11:12 * cemerick realizes this topic is a retread

11:13 dkf: How do I find the length of a vector?

11:13 Chouser: dkf: count

11:13 heh. I don't mean you should count it.

11:13 (count v)

11:13 dkf: thanks :)

11:14 Chouser: cemerick: in what specific way is it tiresome? can we provide tools to ease the pain?

11:14 dkf: is that a lisp thing? why wouldn't there be a (length [0 0 0]) function?

11:16 Chouser: dkf: it's just called count instead of length. In the wide world of APIs, I've seen count, length, and size used almost interchangably.

11:16 nobody ever seems to call it width or height, though.

11:17 cemerick: Chouser: it's just a matter of contrast with other environments. When virtually every directory has just a single file in it, moving around that project structure requires perceptibly more work than it would be otherwise.

11:17 rhickey: length is not a good fit for non-sequental collections

11:17 cemerick: why so many namespaces?

11:18 dkf: ah

11:18 cemerick: rhickey: they mirror existing java packages, or packages/classnames we want to expose to java consumers

11:19 rhickey: cemerick: turning classnames into packages is going to cause that explosion

11:20 Chouser: you can put multiple classes in one directory, right?

11:20 cemerick: rhickey: you mean 'namespaces into packages', yes?

11:20 rhickey: cemerick: now it is the same as Java, yes

11:20 cemerick: yes

11:20 cemerick: Chouser: Sure.

11:20 rhickey: cemerick: no package + class into namespace

11:22 cemerick: rhickey: well, same as Java + 1 -- if Java were to require a directory for the class com.foo.Bar, with a Bar.java file in it

11:22 I realize Java's pretty confused w.r.t. classes functioning as namespaces, but that's the practical effect.

11:22 rhickey: cemerick: that's what I'm advocating against - why isnt the namespace com.foo ?

11:23 cemerick: rhickey: because gen-class is going to search for a com.foo.Bar namespace at init -- or am I one step behind recent gen-class changes?

11:23 rhickey: when implementing a Java class using gen-class, it's exactly the same dir/file granularity

11:24 cemerick: yes, you are behind

11:24 com.foo.Bar is Bar-ths Bar-that in namespace com.foo, file Bar.clj

11:25 dir com/foo/

11:25 cemerick: right, fooey

11:26 Chouser: cemerick: sorry. now you get to undo all those mkdirs :-/

11:26 cemerick: well, that certainly helps

11:26 rhickey: ok, well at least it seems not to be a gripe with where we are going?

11:26 cemerick: rhickey: well, I still have a gripe about one dir per namespace -- gen-class' recent changes just make things a little easier otherwise.

11:29 rhickey: cemerick: too many benefits to playing along with Java packages, but I agree people will have to consider it when organizing their Clojure libs

11:30 bigger than a class but probably finer than your ordinary java package

11:30 cemerick: rhickey: well, consider clojure/src/clj for a moment -- isn't there a way to indicate that tools should look for clojure.set in clojure/set.clj rather than clojure/set/set.clj?

11:32 (BTW, I keep niggling at this because while it bothers me just a little (and I'll get over it), I know that many programmers will be bothered by it a *lot*, especially those coming from python or ruby environments where one-file-per-module is standard)

11:32 rhickey: dropping a segment means dropping a distinction at some point

11:32 Python and Ruby are still class oriented, no?

11:33 cemerick: I'm far less acquainted with Ruby, but you can do a lot in Python without touching classes.

11:33 Just functions in modules, one module per file.

11:33 rhickey: what if clojure.set had a manifest resource, what's to keep that file from conflicting with the clojure.foo manifest resource?

11:34 or any other related items

11:34 cemerick: you mean manifest, as in /META-INF manifests?

11:34 Chouser: You can def functions at a package (module) level in python, but I think you'd usually do all those in a single file in the module's directory -- just like clojure is now.

11:34 drewr: Ruby's and Python's module systems are very different.

11:34 rhickey: cemerick: any resource really, blah.ico

11:35 * drewr favors Python's module system

11:36 albino: in python there isn't any point in creating a package (fs directory) when you can do it in one file with a .py extension

11:37 cemerick: Chouser: It's been a little while (a year, maybe since I touched python much), but packages work just like modules, except their name is defined by their directory name, and their definitions are placed in the __init__.py file in that dir

11:37 Chouser: ah, so you can migrate from foo.py to foo/__init__.py if you need to include other files for whatever reason.

11:38 cemerick: Chouser: yup

11:38 drewr: cemerick: __init__.py is only required to tell the interpreter that the directory contains modules.

11:38 Chouser: I bet it would be pretty hard to talk Java tools into following that kind of layout.

11:38 cemerick: drewr: right, but if you want definitions associated with that package's name, you can put them in __init__

11:39 rhickey: what I'm suggesting is that, if you have a namespace that has multiple resources (whether they're multiple clj files, images files, whatever), then make a directory for the namespace, and pile everything in there. Otherwise, just have a single .clj file for that namespace.

11:39 drewr: cemerick: True.

11:39 cemerick: That requires lib to attempt a couple different loading strategies on each require/use call, but makes life a lot simpler for the simple cases. I think the wildcard is tooling.

11:40 rhickey: I think it is a mistake to ignore what classpath/jars/remote-resource loading brings to the table - I can't make Java aware of some home-made scheme

11:42 cemerick: I guess I'm not following how any namespace conventions that are set forth aren't a home-made scheme -- it's not like a classloader knows that clojure.set maps onto /clojure/set/set.clj natively -- lib has to figure that out, or one has to explicitly load that file.

11:43 rhickey: it knows that clojure.set's resources are under clojure/set/, just from the class package

11:44 cemerick: rhickey: Oh, sure -- but in the simple case where there are no resources, it absolutely doesn't hurt to have clojure.set loaded from /clojure/set.clj

11:46 rhickey: What are the classes called?

11:47 cemerick: I don't follow.

11:47 rhickey: each function becomes a Java class that must have a valid package

11:47 Chouser: clojure functions generate java classes

11:47 * Chouser tries harder to stay quiet.

11:49 cemerick: I would presume that they'd be called whatever they're called now, based on the namespace. I presume at this point we run into the tooling question.

11:50 (right now, clojure.set/intersection is the class clojure.set.intersection__2037 in my repl, which seems fine)

11:50 rhickey: right, before they didn't line up, thwarting tooling (although JSR 45 lets one remap, support varies), now they line up

11:51 I don't want to go down a road that's going to have to change once people want resources, JNLP, ahead-of-time compilation etc

11:52 cemerick: I guess where you lose me here is: where, other than enclojure or some other environment where there is clojure awareness built-in, are we looking to support tooling.

11:52 rhickey: JNLP

11:52 resources, everything that uses classpath

11:52 cemerick: again, if there are no resources, then I don't see what the downside is

11:53 wlr: Given a clojure seq I'd like to print it readably to and re-read it from an external file. Could some kind soul offer up the dual print/read incantations involving *out* and filename?

11:53 cemerick: if there *are* resources, then they get piled into a directory matching the namespace/package, and all's right with the world

11:53 Chouser: wlr: i've got an example sitting around. hang on.

11:54 lisppaste8: dkf annotated #64480 with "automaton" at http://paste.lisp.org/display/64480#1

11:54 dkf: Well, I've gotten rid of the cond

11:54 so it's a little prettier

11:57 could probably get rid of the nth's in tri-take somehow, but I'm going to move on to rule45

11:57 lisppaste8: Chouser pasted "print/read" at http://paste.lisp.org/display/64489

11:57 Chouser: wlr: that's what I do, but I should use "read" instead of "load-file"

11:58 dkf: looks good! + can take more than 2 args: (+ n 1 l)

11:58 wlr: Chouser: Thank you very much.

11:59 rhickey: cemerick: all those are homemade rules every tool is going to have to be aware of, and no Java tools ever will - what if the ns is defined in more than one clj?, if there are resources does the clj move down? etc

11:59 dkf: Chouser: thanks

12:02 cemerick: rhickey: if there are more than one .clj in a ns, or if there are resources, then everything in that ns goes into a directory. It's seems like a straightforward thing to me (perhaps only because of my ignorance of impl details). Regarding tools -- I'd wonder what tool other than something that is already clojure-aware would need to pull up that single file that defines a namespace (/clojure/set.clj, for example).

12:04 Chouser: cemerick: debuggers, for one

12:04 rhickey: profilers

12:07 cemerick: Perhaps I'm assuming too much about which tools people are using for those things. i.e. if I'm using clojure, I'd want to be in enclojure or some enclojure-aware emacs environment, etc.

12:07 rhickey: As I said, there is an JSR that let's one specify different paths and file names, and Clojure emits JSR 45 info, but support varies. Putting things in a path that matches the package/ns, and having that be a general rule, is much more straightforward in all contexts

12:09 cemerick: you mention Clojure aware, but in the case of enclojure for instance, what they are doing is trying to get existing Java tooling to work with minimal change

12:09 cemerick: I guess my opinion would be to rely on tools to catch up with JSR 45. JRuby and Jython have this exact same problem, so it seems like a decent bandwagon to be on, in terms of community demand.

12:10 rhickey: Right, but even without JSR 45, it's no big trick to push the NB debugger or profiler to bring up the contents of this-file-over-here when it needs to show clojure.set.

12:12 I guess I find myself in the unusual position of advocating for the new user. Perhaps my concerns in that regard are unfounded.

12:12 rhickey: cemerick: I don't you've sold the benefits of your approach at all, just downplaying the benefits of following classpath. What's so difficult about creating a dir for a namespace?

12:14 I guess a lot has to do with the granularity of a namespace

12:15 cemerick: It's not about difficulty, it's about simplicity, cognitive overhead, and things working like people would expect them to work. We're trying to fit into a Java ecosystem, but I'll bet serious money that a Java programmer would be very confused about the ns com.foo.bar needing to reside in /com/foo/bar/bar.clj.

12:17 rhickey: why wouldn't he presume everything related to the package com.foo.bar is in com/foo/bar/ and just be surprised and pleased you don't have to have umpteen .java files to define a package?

12:18 would you prefer /com/foo/bar/init.clj?

12:18 erochester: I don't really have a dog in this fight (and my better judgment is warning me to stay out of this, but when has that ever stopped me?), but cognitively, Clojure already breaks the fairly simple directory=package, file=class schema that a Java programmer might have.

12:18 Well, I'm not an experienced Java programmer, and that's the schema I have about them, anyway.

12:18 Someone who know Java better may think of it differently.

12:19 And I may be misreading Clojure too :)

12:19 rhickey: erochester: yes, but these changes unify dir/package/namespace

12:19 not having classes, things diverge there

12:20 cemerick: rhickey: I'm pretty sure that most (if not all) java programmers don't think about "defining a package" -- they define classes that happen to live in a package. They'll want to define functions and happen to live in a namespace.

12:20 erochester: rhickey: Right, and I can see how they would make tool integration much easier.

12:20 rhickey: but technically, there are classes, and they are defined in the source files contained in the dir matching the package/namspace, just like Java

12:21 those source files end in .clj and there are fewer of them, and their names don't correspond to classnames

12:21 * rhickey is not expecting anyone to advocate for file-per-fn

12:23 rhickey: cemerick: would you prefer /com/foo/bar/init.clj? - that's a serious question, is the /bar/bar part the problem?

12:23 cemerick: rhickey: No, the name of the "top level" clj file in a namespace dir isn't a problem either way

12:26 Chouser: It'll be interesting to see how the gen stuff shakes out, but for now I'm experimenting with putting one gen.clj file in each namespace dir: net/n01se/n01se-gen.clj

12:26 Then the various class .clj's next to it (one per class so the generated startup code can find it)

12:26 rhickey: cemerick: when they "define classes that live in a package" they put the code in source files that live in a dir corresponding to the package - I don't see how this is different

12:27 Chouser: in that context, it might be interesting to use "gen.clj" for build-time stuff and "run.clj" or "init.clj" for runtime stuff.

12:27 cemerick: rhickey: agreed, but packages aren't viewed as entities unto themselves in Java

12:27 I guess I'll sit down now, though. :-) I don't have any data or anything to support my claims of new user expectations, so all I've to go on is extrapolating from my personal reactions.

12:29 erochester: This might just be a matter of making this explicit in the introductory docs and in tutorials. The expectations of new Clojure-users (is there a name for this yet?) just need to be managed somewhat.

12:30 I can see how using keeping changing clojure/set/set.clj to clojure/set.clj would be confusing also, since file != module. How do you tell the difference between clojure/boot.clj and clojure/genclass.clj, which are all in clojure, and clojure/set.clj, which is in clojure.set?

12:31 * erochester facesmack

12:31 rhickey: cemerick: it is important. If dirs are truly bothersome we could end up with users avoiding namespaces and lots of fns named blah-foo, where blah should have been a namespace

12:31 erochester: "using keeping changing" => "changing"

12:31 lisppaste8: dkf annotated #64480 with "automaton" at http://paste.lisp.org/display/64480#2

12:31 dkf: so I cleaned up rule45 too, but now I have problems with mutate

12:32 I don't see why it's returning a list instead of a vector

12:33 rhickey: dkf: isn't it returning a vector with a list in it?

12:33 dkf: yes actually

12:33 Chouser: You might want "vec" instead of "vector", to convert the list generated by map into a vector

12:33 dkf: map returns a list then

12:34 rhickey: you either want to apply vector, or better, use vec

12:34 dkf: ah, ok

12:34 oh yea!

12:35 chickachickaaah

12:35 oooh, beast.. unlimited size automaton now

12:35 Chouser: isn't it great when less code gets you more features?

12:35 dkf: absolutely

12:36 cemerick: rhickey: I don't think it'd come to that -- I think of it more of a question of matching expectations and generally making for a gentle learning curve.

12:36 (again, whether or not my impression of expectations is right or not remains to be seen)

12:38 I'd again point out that JRuby and Jython have exactly this problem (mapping Java names to arbitrary resources), so whatever standards enable tooling for them should help clojure as well.

12:39 s/arbitrary/"arbitrary"

12:43 dkf: ok, unfortunately, that apparently isn't actually rule 45 :) but some twiddling of the bits should fix that

12:46 ok, there it is

12:46 it's fast too

12:49 rule45, 90 cells wide, 1000 iterations: "Elapsed time: 991.024605 msecs"

12:50 rhickey: cemerick: the only other way I'd think about it is namespace == class, i.e. no adding a set dir later stuff, all but the last segment is a real Java package and you have resources per package, i.e. potentially shared between namespaces. But there are sticky bits, like the generated fn classes - I'm not sure I can fabricate true nested classes there...

12:51 the other problem is org.myns ends up in Java package org, i.e. you lose a distinguishing level

12:52 no more namespace clojure

12:54 dkf: rule45, 90 cells wide, 1000 iterations: "Elapsed time: 761.859189 msecs" (changed one line slightly :)

12:55 Is holding the automaton state in a ref the best or most efficient way to do this?

12:56 Chouser: if you only need to observe the final state of the whole thing, you could build it iteratively (recursively) and return the result -- no need to mutate a ref.

12:57 rhickey: (take 1000 (iterate mutate [1 0 1 0 1]))

12:57 dkf: and print to screen each iteration, for the pretty final picture

12:58 rhickey: dkf: could you call it something other than mutate :)

12:58 dkf: hahah, yea, why?

12:58 rhickey: cause you aren't changing anything

12:59 dkf: oh yea

12:59 heheh

12:59 rhickey: step/evolve

12:59 dkf: bifurcate?

12:59 step is too general

13:00 Chouser: step-automata

13:01 dkf: indeed

13:02 holy... "Elapsed time: 3.164833 msecs"

13:03 those swaps to the ref taking up the vast majority of time

13:03 rule45, 90 cells wide, 1000 iterations: "Elapsed time: 3.164833 msecs"

13:03 we have a winner

13:05 wait a minute

13:06 I typo'd. dropped the iterate.. but now that I've added the word iterate in there, "Elapsed time: 0.32325 msecs" .. which can't be right

13:07 rhickey: the result is lazy

13:08 dkf: So it's only measuring the last step?

13:11 how can I print out the results? in the step-automata?

13:12 rhickey: dkf: best to avoid side-effects in you main code, just walk through the result, doseq would work

13:16 dkf: ok

13:26 (doseq prn (take 1000 (iterate (step-automata [0 0 1 0 0])))) ? what am I missing?

13:28 I'm still learning to read the docs

13:28 (doseq item list & body) not sure what item is here

13:29 rhickey: doseq takes a name, a seq, and a body of code which uses the name to refer to the current element in the sequence

13:29 (doseq x aseq (prn x))

13:30 dkf: aaah

13:31 as a newcomer, that wasn't intuitive because everywhere else I see binding done in lets. I don't usually see the binding name outside of some kind of enclosing brackets

13:33 but now it says wrong number of args passed to iterate. whereas, without the doseq iterate functioned fine

13:33 (doseq x (take 1000 (iterate (step-automata [0 0 0 1 0 0 0]))) (prn x))

13:34 ok, so the binding is trying to take place in iterate

13:34 rhickey: the entire call to (take 1000 ...) goes where aseq is above

13:36 dkf: It looks like it is to me. You mean put the (prn x) inside the body that returns the aseq?

13:39 to me, it looks like a replace the aseq above with the call to (take 1000 ...)

13:39 rhickey: looks like you aren't using a working call to iterate - it takes a fn as its first arg (iterate step ...) not (iterate (step ...

13:39 dkf: bam, that fixed it

13:40 hmm, iterate worked like that prior to the doseq

13:40 rhickey: I doubt it

13:40 dkf: sorry about that.. lets see.. "Elapsed time: 731.130256 msecs"

13:44 most of that time probably spent printing though

13:48 ok, this is more reasonable (println (last (take 1000 (iterate step-automata [ (90 cells) ])))) "Elapsed time: 611.030474 msecs" and it did indeed print out a changed condition

13:49 that's pretty interesting we did all that without maintaining any state

13:49 rhickey: there you go!

13:52 dkf: 1,000,000 iterations: "Elapsed time: 52809.541073 msecs"

13:54 heh, I wonder if this kind of problem could be multi-threaded.. I suppose you could concatenate two cell spaces together

13:56 Chouser: you're using map in mutate? you could try out pmap

13:56 dkf: same syntax?

13:56 Chouser: not quite

13:56 and you need some 3rdparty .jar -- I've not actually tried it yet.

13:57 dkf: ah

13:59 What about splitting rule45 into rule45First4Bits and rule45Second4Bits and make rule45 cut the vector in half and call to two different threads?

14:00 erm, not cut the vector in half

14:00 Chouser: ah, run your tests in parallel, instead of sequence?

14:01 dkf: I guess just send the vector to each one and one will return a value of 0 or 1.. yea

14:01 Chouser: I bet you'd get some speedup if you used a hash instead of a cond for rul45

14:01 dkf: a hash?

14:02 Chouser: {[0 0 0] 0, [0 0 1] 0, [0 1 0] 1, ...}

14:03 put that in rule45hash, then just: (rule45hash v) to get your new bit

14:03 dkf: hmm

14:04 Chouser: a hash is a lookup table.

14:04 a.k.a. "map", but not to be confused with the map function you're already using.

14:05 dkf: right.. the repl likes it.. so.. instead of a defn, just (def rule45hash {etc})

14:05 Chouser: yep

14:06 actually, the hash will act exactly as your fn does now, so just (def rule45 {...})

14:08 dkf: woops.. did the million iterations again

14:08 it has to best 52 seconds

14:09 interesting.. top says cpu 124% java

14:10 uhoh

14:10 fan on... getting hot

14:10 Chouser: hm.

14:10 dkf: still not done

14:10 might have to kill it

14:11 killed it.. chouser, I think you just software overclocked my computer

14:11 Chouser: heh

14:11 you must have dual cores?

14:11 dkf: yea

14:11 Chouser: the only change was rule45?

14:12 dkf: so maybe hash has some parallelization ?

14:12 yea

14:12 lisppaste8: dkf annotated #64480 with "automaton" at http://paste.lisp.org/display/64480#3

14:12 dkf: commented out the last one

14:13 are commas necessary?

14:13 oh, that was a hundred thousand, not a million

14:14 Chouser: commas are unecessary

14:14 dkf: ok, here we go

14:14 1000 iterations, as before

14:14 rhickey: map will be faster

14:14 dkf: "Elapsed time: 2305.308249 msecs"

14:14 yup

14:15 hmm

14:15 rhickey: not 52:2

14:15 dkf: well, that was 1000

14:15 52 was 100000 iterations

14:15 Chouser: rhickey: map faster than pmap?

14:15 dkf: faster than hash

14:16 52 seconds for 100,000 iterations with map

14:16 much longer for hash, but it seamed to be using both cpus

14:17 Chouser: dkf: you've got pmap in what you pasted

14:17 dkf: whatthe

14:18 rhickey: I get a 12:17 ration map/cond for rule45

14:18 ratio

14:18 dkf: find-doc "pmap" just returns just zipmap for me

14:19 rhickey: map verses cond?

14:19 (yet, pmap still compiles here

14:19 )

14:20 rhickey: map data structure vs cond for rule45, isn't that what you are testing?

14:20 dkf: oh, well, hash-map verses cond

14:20 just hash

14:21 and I just switched pmap back to map and....

14:21 new record for 1000 iterations "Elapsed time: 543.289027 msecs"

14:21 wonder why pmap worked at all.. its it in the lib and just not documented?

14:22 rhickey: right, don't use pmap

14:22 dkf: heh, ok

14:23 rhickey: for map/cond .. were you refering to using a map or using the map function, in rule45?

14:23 or hash-map

14:24 rhickey: I've gotta run, here's a version, with parallelization (which doesn't help here)

14:24 lisppaste8: rhickey pasted "ca" at http://paste.lisp.org/display/64496

14:24 dkf: oh beast.. sweet.. I'll mull this over.. thanks.

14:33 hmm. exception in jsr166y.forkjoin.ParallelArray

14:33 class loader issue of some sort or something

14:34 anyway, I gotta go to.. thanks chouser, thanks rhickey

15:14 you know what the super food of super programmers is?

15:15 fricken oatmeal!

15:27 lisppaste8: rhickey annotated #64496 with "cleaned up a bit" at http://paste.lisp.org/display/64496#1

15:30 dkf: This could make a sick example for the wiki

15:32 by the way, I had the order of rule 45 wrong.. it's 10110100, backwards

15:32 functions the same way, just a different output

15:33 rhickey: has the parallel improved performance?

15:35 rhickey: parallel will improve performance as the vector gets wider, no faster at 80

15:37 dkf: This is a good example because cellular automatons are usually thought of as stateful (state-machines?) and here's one that's stateless, right?

15:39 wait a minute.. I remember you saying in a video that you worked on mathematica... have you read NKS?

23:26 CptPicard: hi guys... what's wrong with my named fns here?

23:26 http://pastebin.com/m2e09c17b

23:26 "Var beer-internal is unbound"

23:28 does one need to defn inner functions too?

Logging service provided by n01se.net