#clojure log - May 18 2009

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

2:24 Lau_of_DK: Top of the morning gents

2:24 markusgustavsson: Good morning

2:50 Lau_of_DK: Anyone here familiar with Symbolic Web, and perhaps a Clojure pendant to it ?

2:54 slashus2: SymbolicWeb developed by lnostdal?

3:45 sopel: hey

3:46 Lau_of_DK: slashus2: yea

3:46 sopel: i'm trying to coerce a bunch of bytes read from a socket to an int

3:46 and the other way around

3:46 any neat way to do it or should i use java?

4:08 Lau_of_DK: a bunch of bytes = an array ?

4:09 sopel: yeah

4:09 (make-array Byte/TYPE 4)

4:09 Lau_of_DK: Then I think Java might be your best option, and cgrand would probably disagree :)

4:09 sopel: it's done here somehow http://gnuvince.wordpress.com/2009/01/29/reading-binary-data-in-clojure/

4:09 but i can't figure out from the code how it's done

4:11 Lau_of_DK: (let [f ({:byte (memfn get) :word (memfn getShort) :dword (memfn getInt)} type)

4:11 You want to find "getInt"

4:12 sopel: yea i tried to call getInt on the array but it says there's no such field

4:13 Lau_of_DK: I think its something he wrote himself

4:13 Although Im not sure, memfn takes a clojure function as far as I recall

4:13 sopel: oh ok.

4:13 i think i got it

4:13 he converts it to a char array first.

4:13 and then calls getInt on it

4:13 Lau_of_DK: (doc memfn)

4:13 clojurebot: "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn."

4:13 sopel: err.. string.

4:13 Lau_of_DK: ooh, clever :)

4:14 Raynes: http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4978

4:14 That's a seriously long function.

4:14 Lau_of_DK: Raynes: We had to debug a function the other day, which was 500 lines long :)

4:15 (no - We did not write it initially)

4:15 Raynes: :o

4:16 Hey, cool, HPaste does Clojure highlighting now.

4:21 cads: can IEEE floating point numbers be printed out and read back in perfectly unchanged in clojure?

4:23 sopel: Lau; argh that doesn't work.

4:24 cads: in ruby i think I did that using printf with a format character for floats, and I think ruby's to-f function automatically read the special format back in to a float

5:36 sopel: how to group a bunch of expressions? i.e. i want to do (if foo (some expr some expr 2) (else something))

5:37 and i want some expr and some expr 2 to be aprt of the if true clause and not some expr 2 being the else clause

5:37 kotarak: (if foo (do (expr1) (expr2)) (do (something) else))

5:38 sopel: thx. can't find 'do' in the reference.

5:38 svdm: it's on the special forms page

5:46 lisppaste8: cgrand annotated #80388 "Enlive selector for quidnunc" at http://paste.lisp.org/display/80388#1

5:47 sopel: any logging package for clojure?

5:47 or should i use java stuff

6:26 kotarak: sopel: apache commons logging is often mentioned as a good solution

7:22 Raynes: "Compared with Paul Hudak, John Hughes, Simon Peyton Jones, and Phil Wadler, Rich Hickey is chopped liver :-) "

7:23 That's low. :\

7:31 Cark: where did you catch that ?

7:54 Chouser: well, that worked out nicely -- a Java lib wanted a object with a particular interface, but it was mainly going to just pass it back to me later.

7:55 so I used proxy to make an APersistentMap that delegates to a regular hash-map like I was going to use anyway, but the proxy also implements the Java lib's interface.

7:56 my clojure code can happily ignore the fact that it has a particular Java interface, and the Java code can ignore that it's a hash-map

7:57 Cark: nice =)

7:57 but

7:58 hum no forget it, had a question but you explained it already !

7:58 Chouser: :-)

7:58 the Java API is google protobufs, for which the Java API is quite nice.

7:59 rhickey: Chouser: neat

7:59 Chouser: um. that came out awkwardly. but anyway.

7:59 Cark: ah, you are using protocol buffers in an application ?

7:59 is this to interface with google in some way ?

7:59 rhickey: Chouser: sorry, I got pulled away the other day - did you go with map with IRefs or IRef to map?

8:00 Chouser: the message objects themselves are immutable, with a handy builder interface (also immutable)

8:00 and all the required arg types for the various RPC pieces are abstract interfaces.

8:01 rhickey: map of IRefs. I spent a couple hours on the phone with abrooks beating on the subject, and am happy with the solution.

8:03 The difference from what I described earlier is not trying to close over pieces of the obj's data, but instead pass in the whole object when needed.

8:03 rhickey: ok

8:03 Chouser: this means, for example, that instead of trying to make the object the state of the main agent, the state of the agent is just nil and the obj is passed in as the next arg.

8:03 tbb: hi all, i have what feels like a silly question. within some dynamic bindings I start a thread, how can i make the bindings in the thread point to the same objects?

8:05 kotarak: tbb; you could do (Thread. (fn [] (binding [a a b b c c] (do-thread-things)))). But you have to know what you want in advance.

8:06 tbb: kotarak, thanks, i thought the same thing, maybe I made a mistake, let me double check

8:07 kotarak: tbb: I haven't tested, but it seemed to be an obvious idea.

8:08 rhickey: kotarak: you have to capture the bindings with a let, then re-establish in the fn

8:09 kotarak: Ok. @ tbb => let then re-establish in the fn.

8:09 * kotarak thinks, a channel of gurus is really handy. :)

8:09 tbb: is the let outside of the fn?

8:10 kotarak: I would think so.

8:10 Ah. Of course.

8:10 The binding in the new thread already sees the old bindings.

8:11 So you have to do: (let [a a b b c c] (Thread. (fn [] (binding [a a b b c c] ...)))

8:11 Now the a b c in the binding are coming from the let.

8:11 Which contain the modified bindings from the parent thread.

8:13 tbb: thank you! trying it out now

8:15 rhickey: I had this idea last night (again, actually an old one) about a stack-discipline context-cache, like bindings but not dynamic name scope, for threading values to nested contexts without poisoning the call chain, since about half the use of binding, or attempted usage, is in that category. Could use for monads etc. It would be captured by fn. Only half-baked at this point.

8:33 tbb: kotarak, rhickey: it works just fine, the problem was a macro in between, thanks

8:34 rhickey: tbb: you're welcome. I'm surprised no one has written as with-captured-bindings macro yet

8:35 kotarak: There was on the list some while ago, IIRC

8:35 Chouser: I was sure I saw one. It's not in contrib?

8:37 jdz: anybody experiencing problems with using classes that are in locations that are added using add-classpath?

8:37 kotarak: jdz: don't use add-classpath. Only from the REPL but not for production.

8:37 There are currently changes down in trunk, which influence add-classpath.

8:38 jdz: i have noticed :/

8:38 hoeck: ,(proxy [clojure.lang.ISeq] nil (seq [] ()))

8:38 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessDeclaredMembers)

8:39 hoeck: ah, too bad clojurebot doesn't allow this, on my machine, the above expression returns (nil)

8:39 jdz: kotarak: is there going to be no way to add classpaths dynamically at all?

8:39 hoeck: is this correct or is this a bug?

8:40 kotarak: jdz: add a directory to your classpath, unzip the jar in this directory an runtime and the classes will be found.

8:41 jdz: i know there are many ways to work around that. but that does not answer the question...

8:41 Chouser: hoeck: I think .seq methods aren't expected to return empty lists -- either a list of stuff or nil

8:42 jdz: It's not really supported by Java.

8:42 kotarak: jdz: To my information adding dynamicly stuff to the classpath was always broken and hacky.

8:43 jdz: well it at least worked up to recently

8:43 Chouser: oh, really? I've never had much success.

8:44 rhickey: add-classpath is in conflict with modularity, since it requires a singly-rooted classpath-tree.

8:45 also, it is a problem for a library (e.g. Clojure's) to load classes on behalf of consumers, since they might have visibility to something the library doesn't

8:46 I have been fixing the latter, moving Class.forName calls to the consumer of things like import, ns and new

8:46 this should greatly improve the story for Clojure in contexts like OSGi/Eclipse/ Netbeans, web app servers etc

8:48 jdz: well i'm thinking of how to get swank running now...

8:48 rhickey: add-classpath was only ever intended for the "I'm already running and I found this lib on the net I want to check out" scenario. Once you've got a library you care about, you need to put it in your classpath using standard means

8:48 kotarak: jdz: use release? Or pre-changes SVN?

8:49 jdz: ye, might as well

8:50 rhickey: what I'm thinking is there will be a narrowly-defined context in which you can get the shared root loader, like in the repl.

8:51 swank uses add-classpath?

8:51 * Chouser proxies Ref

8:51 jdz: yes

8:52 hoeck: Chouser: I thought, since () implements ISeq, i can safely return it from a seq method of any (derived) clojure collection and get the same thing back.

8:52 rhickey: hoeck: seq must return non-emtpy seq or nil

8:53 hoeck: rhickey: ah, okay

8:53 jdz: rhickey: swank also tries to compile itself on demand

8:54 rhickey: so it uses add-classpath twice

8:54 rhickey: Help wanted: http://groups.google.com/group/clojure/browse_frm/thread/ef2eee0a2ea12b76

8:55 jdz: what does it add?

8:56 jdz: rhickey: first it adds the location of .clj files based on the elisp file it is being loaded from. second it adds classroot for compiled files when compiling (or loading if already compiled).

8:56 rhickey: the first addition could be skipped by adding the path to the classpath argument when starting jvm

8:57 rhickey: the second one is trickier; the solution might also be to do things on emacs side, not clojure

8:58 rhickey: btw, what environment do you use for developing yourself?

8:59 kotarak: rhickey: should be something using concurrency? maybe the ants? That was what caught me, although I don't do much concurrency work. The whole Ref/Agent/Atom system is a main selling point, I think.

8:59 jdz: for me the selling point is the easy interop with Java

9:00 and the functional side of clojure

9:00 Chouser: ants is so 2008

9:00 kotarak: Chouser: you are free to present something modern. :) ;)

9:00 Chouser: :-)

9:01 rhickey: jdz: I use Aquamacs (with clojure-mode only) for Clojure code, and IntelliJ for Java. Have been playing with enclojure (much better now) and IntelliJ's La Clojure plugin, although I don't understand the latters' relationship (if any) to a repl yet

9:01 kotarak: I'm not experienced in concurrency. So I don't know any nice examples for 4 minutes.

9:02 Chouser: If there were a Java entry, what would they show?

9:02 rhickey: kotarak: One of the interesting things about Clojure is its success in spite of the fact that only a small percentage of its users are currently leveraging its concurrency features.

9:02 Chouser: I mean, what do Java people like to do with their language?

9:03 rhickey: Chouser: get paid

9:03 Chouser: If you could demo *that* in 4 minutes, I'd be impressed.

9:03 jdz: rhickey: i like the fact that i get concurrency for free when i want it (if the code is written properly, of course)

9:03 kotarak: rhickey: Well. For me these are reasons why I *love* clojure: immutability be default, Lisp (Lisp-1 in particular), nice integration of vectors, maps and sets, small footprint of the core, nice community

9:04 Chouser: Yeah, I was chugging the kool-aid before I understood any of the concurrency features.

9:04 kotarak: And the Java interop, although I don't particularly like Java itself.

9:04 rhickey: the 4 minute demo is actually an interesting problem. Last year, they had assigned a task (a twitter client) and everyone was showing their implementation of the same thing

9:04 kotarak: But for the libraries it awesome.

9:05 The 5-minutes talk is the king of talks.

9:05 rhickey: why use Clojure instead of JRuby/Groovy/Jython/Scala is also a question the presentation needs to answer, indirectly

9:05 clojurebot: why not?

9:05 Chouser: Coming from non-lisps, I love how pleasant I can make an API. Having written a library of functionality, it takes a matter of a minutes to layer functions and/or macros on top to make it absolutely beautiful to use.

9:06 eevar2: rhickey: because it's a lisp

9:07 no idea how to demo that w/o scaring half the people away, tho ;)

9:09 rhickey: I think FP/immutability as the default, Lisp, abstraction-based lib, and built-in concurrency story are all distinguishing features, but Scala can do FP and has actors, Groovy/Ruby/Scala DSLs. Superficially, people might not be able to see the distinctions, that's what we have to tease out (in 4 minutes)

9:10 kotarak: Also nice: the concise of Clojure code. Do something non-trivially in less code, than the rest?

9:11 rhickey: I think people that just want dynamic Java should go Groovy, people that want Java++, Scala, people with existing Python/Ruby Jython/JRuby. Who does that leave and why are you here? :)

9:11 tWip: lispers forced to live in the jvm?

9:12 gnuvince_: People who want a fun and simple language that has access to an established platform.

9:12 kotarak: Because the others are no Lisp. :) I avoid macros like the devil the holy water, but it's nice to have them available. So maybe homoiconicity or whatever it is called?

9:12 Chouser: I never wanted Java, so that puts me in the Jython/JRuby category.

9:13 seq abstraction and immutability are why I came here. And macros.

9:13 rhickey: Chouser: I wasn't saying people that know Python/Ruby, but more people that wanted to move that code

9:14 Chouser: oh, and dynamic typing -- that's why I finished my brief stint with Scala.

9:14 rhickey: immutability is a definite feature that doesn't necessarily seem like one at first, I think

9:15 I like to think that people find their Clojure programs more robust and easier to understand, but maybe they don't?

9:16 kotarak: I think they are easier to understand (if you are a Lisp guy) because they are so concise. With Java I scroll around all the day to skip those getter/setter ged�hnse stuff.

9:16 marklar: rhickey: definitely, like kotarak said, how concise the programs are is amazing

9:16 rhickey: Practically there are many hurdles, esp. the fact that many will not be able to parse the syntax at all, and thus not know what they are looking at. The focus is supposed to be on code, not slides.

9:16 kotarak: With Clojure its just less stuff polluting the cache in my brain.

9:17 gnuvince_: I was speaking with a few friends who are mostly C and C++ programmers yesterday, and one described the idea of mutability as "abject".

9:18 "If the CPU can mutate values, why couldn't I?"

9:18 kotarak: But this is also a problem for others, no? The Scala syntax is also not so intuitive when you never saw it before the 4min talk.

9:18 rhickey: kotarak: all the other langs will be showing x.foo in some form

9:18 hoeck: I was first afraid of the fact that all clojure datastructures are immutable by default, and really wondered wether one can write useful programs with such a limitation

9:19 * kotarak thinks about a 4min Haskell talk. *shudder*

9:19 rhickey: hoeck: and now?

9:19 hoeck: well, I've read that paper about necessary and accidential complexity ...

9:20 kotarak: Ah: Another point: clojure's consistency in wide areas: (swap! atom f args) (alter ref f args) (update-in map [keys] f args) (send agent f args) ....

9:20 Chouser: tarpit

9:20 kotarak: So the abstractions are a big point.

9:20 gnuvince_: I think that as long as you're not looking to squeeze out every single cycle out of your CPU, immutability really ought to be the default. I feel it makes code easier to understand, not to mention that persistent collections are a big plus.

9:21 hoeck: and I really appreciate the way clojure works, and I try to build more immutable code in my day job, because its way cleaner and easier to understand

9:21 kotarak: gnuvince_: OCaml also has immutability be default and really squeezes a lot out of the CPU...

9:21 So it's not necessarily a trade-off.

9:21 Although, the collections are mutable there. You are right.

9:22 rhickey: I was thinking about showing the Amazon SimpleDB lib, which, in 300 lines, provides a full extensible API as well as an embedded DSL for queries. Has anyone looked at it?

9:22 gnuvince_: kotarak: yeah, arrays can be mutated with arr.(1) <- x

9:22 clojurebot: x is w

9:22 gnuvince_: or something like that

9:23 kotarak: gnuvince_: yes but local are immutable be default, also the "O" part has some simple syntax for immutable objects

9:23 rhickey: I imagine a small ring/compojure/enlive demo could work

9:24 gnuvince_: kotarak: no need to convince me :)

9:24 rhickey: I don't know enough about any of them to write one

9:24 gnuvince_: kotarak: but I was not able to convince guys who've been x++'ing their code for 15 years

9:24 rhickey: the consensus was everyone was tired of web apps as demos

9:25 kotarak: gnuvince_: -.- "Old dogs don't learn new tricks." as the proverb knows.

9:25 Chouser: I wonder if the ring/moustache stuff would turn some head

9:25 oh

9:25 rhickey: since every lang now has a web-site with a couple of lines library now

9:25 Chouser: "heads", and nevermind.

9:25 gnuvince_: kotarak: maybe you're right

9:25 eevar2: how about a slick swing app?

9:26 gnuvince_: Took me a while to appreciate immutability, and I still sometimes question it.

9:26 rhickey: I really liked the multithreaded Life demo video that had 1/2/4 cores side-by side, but I'll only have a dual core with me

9:28 http://www.youtube.com/watch?v=CFCYVfApPUc

9:29 kotarak: Showing seq abstractions and generic functions working on a variety of data structures is probably lacking the *BOOM*-effect for such a talk.

9:30 gnuvince_: For round 2, I think a simpledb demo would be cool

9:30 rhickey: gnuvince: I think round 2 should feature the work of the community, not mine

9:31 gnuvince_: rhickey: ah, ok.

9:31 For round 1, I'd say that a Java crowd would be most interested in the Java interop access

9:31 Chouser: that life demo is nice.

9:31 rhickey: gnuvince_: but that's something all the langs have

9:31 gnuvince_: We just need to come up with a short example that shows that, but that also highlights Clojure's specific strenghts.

9:32 Chouser: shows off community collaboration as well

9:33 rhickey: Chouser: it would be nice in round 2 to give a sense of the community as a whole, esp. libraries

9:33 e.g. for Scala, Lift is a big selling point

9:33 for Groovy, Grails

9:34 Chouser: for Clojure, error-kit

9:34 Chousuke: :P

9:34 Chouser: hehe :-)

9:34 rhickey: Obviously Clojure doesn't have as mature libs, being much younger

9:34 Chouser: error-kit confuses me, so...

9:34 clojurebot: Who??

9:34 kotarak: lazymap ;)

9:35 gnuvince_: It might be just me, but I think showing yet another web framework in yet another language is gonna get boring

9:35 Lift, Grails, Rails on JRuby and JDjango...

9:36 Chouser: but that's what people use their languages for now. Like you had to have some kind of GUI story in the 90's -- tk bindings or *something*

9:36 Chousuke: the web stuff would be good for showing of DSLs in clojure though

9:37 like enlive's selector stuff or clj-html

9:37 showing off* too

9:37 rhickey: A web thingy showing something unique about doing it in Clojure might still be interesting, but DSLs are available elsewhere too

9:37 Chouser: but if you have a compelling demo, you can just toss in a line about "Clojure has great web app support to get your site running with just a couple lines... but what language these days doesn't?" ...and move one.

9:37 gnuvince_: Chouser: maybe, but I don't think I'd want to switch to a very foreign language just for a web framework.

9:38 Chouser: gnuvince_: a lot of people did that for Ruby, I think. Of course they may regret that decision now...

9:38 Chousuke: we could demo clojurebot :P

9:38 gnuvince_: Chousuke: isn't that in Java?

9:39 Chousuke: well, most of it is, yeah.

9:39 the actual irc stuff is handled by pircbot

9:39 Chouser: really!?

9:39 oh

9:39 Chousuke: but all the interesting features are in clojure :)

9:41 gnuvince_: Is there a short and simple demo that could be done with agents to show off Clojure's concurrency features?

9:41 kotarak: Someone just mentioned on the list the dynamic modification of a running program as it was done in the ants demo. That would also be cool.

9:41 gnuvince_: Maybe downloading a bunch of files, but no more than 5 at a time, something like that?

9:43 Chousuke: I don't think it'd show off the concurrency features well enough. :/

9:43 gnuvince_: Chousuke: what can you show in just 4 minutes that would give Java a people a reason to look at a Lisp dialect with dynamic typing instead of Scala

9:44 Chousuke: that's the problem :P

9:44 * don333 sees like joining in the middle of an interestring discussion

9:45 kotarak: don333: http://clojure-log.n01se.net to catch up ;)

9:45 don333: will look now, thanks :)

9:45 gnuvince_: Chousuke: this is why something simple that people not necessarily familiar with Lisp-like languages can grasp and can say "that's cool" would be best.

9:46 rhickey: For the community part, I think it would be possible to show the value of using the core data structures everywhere, you know, 1 line to load xml from a web site, another to filter and reshape it, another to stick it in a db, and a couple more to put up in a Swing or html view. In most langs each of those things would have their own object-based api

9:46 Chouser: kotarak: that's updating only once a day now. :-/

9:46 kotarak: Chouser: Oh. Ok.

9:46 rhickey: i.e. the value of non-oo libs

9:46 don333: kotarak: either I can't use it or it doesn't show the recent discussion

9:46 cp2: mornin'

9:46 exams today, no class :)

9:47 kotarak: don333: see what Chouser wrote: update now only once a day... :/

9:47 rhickey: maybe some zipper modifying a tree?

9:48 Chouser: zippers are most interesting after you're already sold on immutability. Otherwise they just look complicated.

9:49 don333: rhickey: is that what you described possible in Clojure?

9:49 rhickey: don333: sure

9:50 don333: because I came to #clojure exactly to find out if it's better to devote my time to Scala or Clojure as "the next for the JVM"

9:50 sopel: rhickey; congrats on clojure, great job :)

9:50 rhickey: don333: I think both will succeed

9:50 sopel: thanks

9:50 sopel: i was really hurting not being able to do any lisp

9:50 and now there's a reason at last

9:53 don333: rhickey: where can I find examples for Clojure code doing something like what you described?

9:53 or is Chouser working on a demo? :)

9:53 sopel: don333; lisps are superior to javascript-like languages which Scala seems to be basing on the examples ;)

9:53 rhickey: I think the Clojure libs + data structures as legos would be a great, distinguishing demo. When other langs read XML they get a DOM, when they read from a db they get recordsets, when they want to do logic on them they need to pour into collection classes, when they want to view them, they need to create model classes. A plethora of APIs, no interop

9:53 don333: sopel: I know Lisp (CL that is)

9:54 sopel: don333; then i'm surprised that you're even considering scala. looks ugly :)

9:54 don333: I see Scala as an improvement over Java (language) and I have to code Java on the job

9:55 I know nothing about Clojure except for the title "FP on JVM"

9:55 and it made me curious

9:57 sopel: don333; well I'll always pick a lisp over any imperative language, and you can use all of Java from Clojure

9:57 rhickey: don333: most Clojure libs work like I described

9:58 don333: so, I should look at Clojure source then?

9:59 sopel: that's what I'm most interested in, if I could use CL I'd use CL

9:59 things like Hibernate, servlets, EJB or annotation support is what I'm after

9:59 Chouser: don333: there is a CL for JVM

10:00 but you don't get Clojure's yummy immutability, concurrency support, etc.

10:00 rhickey: don333: any example programs, blogs etc

10:00 guinea: How do I download/install a contrib library? I checked out the -readonly tree from SVN and tried (add-classpath the-src-directory)

10:01 don333: rhickey: I'm digging through clojure.org in the mean time

10:01 sopel: guinea; you have to build it with ant first and then add the resulting jar to classpath

10:02 guinea: sopel: thanks

10:02 rhickey: don333: but you won't find Hibernate or EJB, that's just more of the same

10:02 guinea: the ant demo is a really fun intro. I was having fun adding user interaction on the fly, and learning a lot doing so.

10:03 don333: yes, I get that - but knowing that I won't be the first to try (and succeed) joining e.g. EJB code with Clojure code would help

10:05 and I didn't find that (or the annotations) in "Java Interop" on clojure.org

10:09 rhickey: don333: If you are doing EJB, annotations etc then Java is still driving the architecture (it's ok, that's where you are), so using Clojure there will be more about calling Clojure-based logic from Java. You can write Java classes in Clojure, but hopefully the need for that would be limited. There is no annotations support in gen-class yet.

10:09 don333: rhickey: thanks, that was very helpful

10:43 Chouser: this is the first time I've written Clojure code with the intention of wrapping it in a Java API.

10:43 I know others have done so, but it's pretty interesting.

10:44 rhickey: Chouser: do you control the interface or are you implementing an external interface?

10:45 Chouser: a bit of each. protobuf provides a set of interfaces for me to implement, but that doesn't cover all the bases, so I'll have some API of my own.

10:46 I'm currently expecting to provide a single class with a bunch of static methods for creating the various objects needed.

10:46 not "normal" Java, I suspect, but I think it'll be easy enough to use.

10:46 rhickey: interfaces + proxies + factories is ideal, IMO

10:47 Chouser: yes, is going nicely so far. protobuf's supplying the interfaces, I'm writing proxies now, and will layer a factory piece on top.

10:47 the protobuf objects all use interfaces and factories. ...I'm not sure there's a single public constructor in there anywhere.

10:48 rhickey: public ctors have fallen into disfavor, everyone hates them for testing reasons at least

10:48 Chouser: interesting.

10:49 rhickey: http://code.google.com/p/google-guice/

10:49 even factories

10:50 Chouser: I was happy to see a nice constructor for Ref, though. I've got a (proxy [Ref RpcController] [{...}] ...) that looks quite nice.

11:18 what are the latest thoughts on handling of agent errors?

11:19 watchers aren't triggered on error, are they?

11:31 rhickey: Chouser: same thoughts, error queues

11:45 Chouser: rhickey: you'd register an agent with a particular queue?

11:47 rhickey: Chouser: there'd be a default, or yes, register one

11:48 Chouser: this is a PersistentQueue, or something on which you can register a handler?

11:50 rhickey: Chouser: the agent side shouldn't care

11:50 this is waiting on abstractions for queues so that will be possible

11:51 Chouser: oh, ok.

11:52 rhickey: the write part of a queue abstraction might not look any different from IFn

11:52 but some queues could block, or have transactions, or yield message ids etc

11:52 Chouser: nice

11:57 rhickey: so, perhaps the agent side need wait on nothing else, just add an on-error handler fn, like validator

11:59 biilly: when you guys start a slime-repl, do you have to hit RET multiple times to get from inferior-lisp to the slime-repl?

12:04 replaca: biilly: nope

12:05 Chouser: are you doing a general purpose protobuf implementation for Clojure?

12:06 Chouser: there's hardly anything to do to use protobuf nicely in clojure.

12:06 biilly: hmm, thanks. aloso if i lauch javadoc within the slime-repl it hangs, and i have to go to the lisp-inferior buffer and hit RET - but only once

12:06 replaca: Chouser: cool

12:06 Chouser: no, I'm doing a closed-source proprietary RPC thing built on protobuf

12:07 replaca: Chouser: for your new job?

12:07 Chouser: yep!

12:07 replaca: Chouser: using clojure at work, yay!

12:07 stuartsierra: billy: it takes several seconds before slime-repl takes over, that may be what you're seeing.

12:07 Chouser: yes, exactly. it's in a bit of a probationary period here, so we'll see how it goes over.

12:08 replaca: Chouser: are there other lisp heads there or is the whole lisp thing weird to them?

12:09 Chouser: lisp and java are both less than popular. ...got a bit of a hill to climb.

12:09 replaca: Chouser: what's the default implementation environment?

12:10 Chouser: different projects are using tend in different directions, but more common are ruby, php, and C++

12:10 biilly: stuartsierra: it takes a few seconds to connect, which it does, but it will stay in the inferior lisp buffer indefinately until i hit return

12:10 stuartsierra: biilly: huh, dunno then

12:11 Chouser: but I'm on a smart team with open minds and minimal managerial overhead, so I'm pretty hopeful.

12:11 replaca: Chouser: interesting. In my day job, I'm the PHB & I'm pretty hard-nosed about a single platform

12:12 (and in our case it's .Net, so no Clojure)

12:12 but I have pushed IronPython and other scripting stuff to try to crack the battleship

12:12 Chouser: well, as I said, we'll see how this goes. This work will be classified as "prototype" until it can prove itself.

12:13 it may get re-written in C++ if I can't prevail.

12:13 in which case I'll have to cash in these parens for all the extra LOC I'll need.

12:13 replaca: Chouser: well, I hope you do! It will be fun to see Clojure get more and more real world traction.

12:14 Chouser: well, you already wrote the javascript thing, maybe you can just do a clojure to C++ converter

12:14 then noone will know better

12:14 :-)

12:14 Chouser: right

12:14 sure

12:18 djpowell: re: why clojure; I'm pretty much using clojure for the seq

12:18 abstraction. being able to do sick things with multiple

12:18 resultset-seqs is really cool. and the common interface of

12:18 datastructures rather than objects, makes stuff easy to test. and the

12:18 interative development of course is a big thing.

12:18 (urgh - fill-mode - how did that happen...)

12:31 hiredman: ~whose job is it to port clojure to c++

12:31 clojurebot: You don't have to tell me twice.

12:31 hiredman: bah

12:32 ~whose job is it to port clojure to c++?

12:32 clojurebot: that's Kisu's job

12:34 danlarkin: uh oh, a lurker

12:38 replaca: well, now he has a job!

12:38 get to work, Kisu!

12:38 hiredman: ~whose job is it to make sure everyone has a job?

12:38 clojurebot: that's unlink's job

12:40 kwatz: heh, that's a clever bot feature

12:41 hiredman: job assignment is very useful in parallel distributed programming

12:42 danlarkin: ha

12:43 * kwatz groans

12:55 Chouser: (.run #^RpcCallback done msg) works, but (.run done msg) produces: java.lang.IllegalArgumentException: No matching method found: run for class com.google.protobuf.RpcUtil$1 (NO_SOURCE_FILE:0)

12:56 (supers (class done)) ==> #{java.lang.Object com.google.protobuf.RpcCallback}

13:08 rhickey: Chouser: is it overloaded?

13:09 Chouser: yes, there's a .run that takes Message, and one that takes Object

13:10 the 'done' object is probably being created by one for these: http://code.google.com/apis/protocolbuffers/docs/reference/java/index.html

13:11 rhickey: is the actual class of done private/nested etc?

13:12 Chouser: user=> (show done)

13:12 === static com.google.protobuf.RpcUtil$1 ===

13:12 [ 5] run : void (Message)

13:12 [ 6] run : void (Object)

13:13 So it's a static (?) nested class produced with generics

13:13 rhickey: is there a reason you want reflection here?

13:14 Chouser: no

13:14 I would have hinted this eventually for performance anyway

13:14 rhickey: sometimes generics /inheritance or access specifiers preclude resolving an overload without a hint - you could hint msg as well?

13:15 i.e. would that have made it go away too?

13:15 Chouser: no, I hinted the Message arg first, without success

13:17 (.run done #^Message msg) ==> java.lang.IllegalArgumentException: No matching method found: run for class com.google.protobuf.RpcUtil$1

13:17 rhickey: Chouser: andthe type of msg?

13:19 Chouser: (class msg) ==> qdc.motu.Motu$GetLogIdsResponse

13:19 (supers (class msg)) ==> #{com.google.protobuf.AbstractMessage com.google.protobuf.Message java.lang.Object com.google.protobuf.GeneratedMessage}

13:22 I'm happy with my workaround, but if you want code to reproduce this I imagine it'd only be a couple lines + the protobuf.jar

13:22 let me know if you want that.

13:22 rhickey: Chouser: sure

13:32 lisppaste8: Chouser pasted "generics vs. hinting" at http://paste.lisp.org/display/80440

13:37 rhickey: Chouser: where can I get the jar?

13:39 Chouser: http://code.google.com/p/protobuf/downloads/list We're using 2.0.3

13:39 hm, you may have to build the jar. I guess I could upload the one I have built somewhwere.

13:39 rhickey: making 2.1 now

13:39 ick

13:40 Chouser: ?

13:40 rhickey: c++, make, etc

13:41 technomancy: rhickey: I'm trying out your sdb lib; looks pretty handy.

13:41 rhickey: technomancy: yay!

13:41 technomancy: it'd be nice if the dependencies could be automated, but it looks like the Java SDB lib is not available in any public repositories.

13:42 I wonder if that's because of its license.

13:46 rhickey: is the Amazon HTTP server endpoint hard-coded into the java lib?

13:47 I was thinking about testing it out against MDB, which is supposed to be a free drop-in SDB alternative that you can run locally: http://gradvs1.mgateway.com/main/index.html?path=mdb

13:47 guess I can always use /etc/hosts =)

13:49 rhickey: technomancy: if you make your own client you can set things up with AmazonSimpleDBConfig: http://s3.amazonaws.com/awscode/amazon-simpledb/2007-11-07/java/library/doc/com/amazonaws/sdb/AmazonSimpleDBConfig.html

13:49 setServiceURL

13:49 technomancy: rhickey: cool; will check that out.

14:00 it looks like the -> form is kind of similar to doto, is that a fair statement?

14:00 Chouser: they're both macros the insert stuff as the first arg of each form

14:00 what they insert is different

14:00 technomancy: the main difference being that doto calls always affect the first argument, while the receiver of -> methods is updated

14:01 Chouser: what they return is also different.

14:01 technomancy: right; -> seems to work more like reduce in a way.

14:02 </thinking-out-loud>

14:02 Chouser: '..' is also somewhat similar

14:03 dnolen: -> is great, you can read left right instead of inside out.

14:06 Cark: -> makes me think about monads

14:06 somehow

14:06 liebke: I use doto when I'm working with methods with side effects, like updating a mutable java object, and -> when I'm working with functions on immutable data structures that return new values

14:08 dnolen: ,(-> {} (assoc :k1 'v1) (assoc :k2 [0 1 2 3]) (update-in [:k2 0] inc))

14:08 clojurebot: {:k2 [1 1 2 3], :k1 v1}

14:10 Chouser: (-> protobuf.Mine/newBuilder (.setFoo 1) (.setBar "bar") .build)

14:12 rhickey: Chouser: the declaring class is not public, but run(Message) is found, matches, and dominates run(Object), so Reflector tries to find run(Message) declared in a public base interface/class, but only run(Object) is found in com.google.protobuf.RpcCallback

14:13 liebke: Chouser: does that work? Unless .setFoo and .setBar return the updated version of newBuilder, it doesn't seem like that would work. This is the kind of stuff where I use doto

14:14 Chouser: liebke: protobufs are immutable, and the builders return new instances with the values set.

14:14 liebke: ah, interesting!

14:14 Chouser: yes, I thought so.

14:15 hiredman: sounds familiar

14:15 Chouser: rhickey: weird. It would be illegal to call run(Message) because it's not public?

14:16 rhickey: Chouser: reflection needs a Method of an accessible class

14:16 hiredman: there was some paper about adding some ability to java (I forget what) that proposed sort of splitting constructors, so that the object was not created till the constructor was finished, but the constructor could set fields on a sort of proto-object

14:17 rhickey: run(Message) is a public method of a non-public class

15:13 replaca: hiredman: have you considered having clojurebot tell us who made a change in addition to the rev and comment?

15:13 I often find myself wondering

15:18 hiredman: N

15:18 er

15:18 I will look into it

15:23 biilly: i'm trying to add a remote javadoc; if javax. is already set, will javax.servlet be ignored?

15:25 stuartsierra: biilly: I think so, yes

15:25 biilly: would the work-around be to install the javax.servlet docs as local?

15:27 stuartsierra: Maybe, or replace "javax." with more specific sub-packages.

15:28 biilly: will try, thanks

15:29 cgrand: billy: I think that changing line 70 of javadoc.clj to: (rseq @*remote-javadocs*)) could do the trick -- I'll fix it

15:30 replaca: hiredman: just an idea :-)

15:32 hiredman: I think it is entirely possible, the only problem is clojurebot has a recuring anonymous function, so to change it's behaviour I would need to restart clojurebot

15:34 replaca: oh yeah, obviously no hurry at all

15:34 I can't believe that clojurebot is at 5 9s uptime yet :-)

15:34 markusgustavsson: A bit off topic - has anyone here used scons to build C++ code on linux? I found a #scons group but it seems pretty dead :)

15:36 hiredman: replaca: nah, I just tend to alter things while it is running, and then forget, and then restarting it becomes a pain

15:44 replaca: hiredman: ahh, i see

15:51 stuhood: ,(source map)

15:51 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

15:52 stuhood: hmm, could have sworn that was in Mark V's presentation

15:53 stuartsierra: it's in c.c.repl-utils

15:53 stuhood: mmm

15:53 thanks

15:54 ,(clojure.contrib.repl-utils/source map)

15:54 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.repl-utils

15:55 grosours: plop

15:59 hiredman: ~def map

16:04 stuhood: hiredman: i was thinking you could use (source) to dump the definitions of all of the interesting functions in clojurebot

16:04 which would make restarts easier

16:05 stuartsierra: I think (source) reads from files, though.

16:05 hiredman: yeah, it would have to

16:06 that or decompile java bytecode to clojure source

16:06 which, would, uh, be :(

16:07 Chouser: decompile, de-macroexpand, ...

16:07 hiredman: yeah

16:07 that would be a drag

16:07 Chouser: de-macroexpand might be fun. run it on your own code to discover macros you meant to use.

16:08 danlarkin: sounds like an idea my buddies and I had in college

16:08 write a program in APL that would write all other possible programs, until you had one that gave you the answer you wanted with the inputs you gave

16:09 needless to say, we didn't pursue it very far

16:11 hiredman: someone wrote a clojure function that given an input, and an output, would search the fn's held by vars in all available namespaces for one that matched

16:12 danlarkin: that's kinda neat

16:14 durka42: as long as all your functions are referentially transparent

16:14 is this function called i-wonder-what-this-button-does?

16:14 hiredman: I forget

16:15 it was on the google group months back

16:36 lisppaste8: sh10151 pasted "DFS" at http://paste.lisp.org/display/80454

16:36 sh10151: I need a quick sanity check: is this a reasonable depth-first-search implementation?

16:36 and by reasonable I mean it doesn't end up generating a lot of garbage

16:37 not sure how the lazy sequences work exactly

16:38 Chouser: sure

16:47 devinus: is knowledge of java required for working closely with clojure?

16:48 gnuvince_: devinus: it definitely helps.

16:48 Chouser: eventually, yes. But I don't think you need much java knowledge to get started, and probably never deep particularly deep groking of Java.

16:53 danlarkin: Hey Chouser, while you're here, did you see my error-kit + test-is email on the ML?

16:53 Chouser: no, sorry.

16:54 hm, there's another error-kit message just now...

16:55 sh10151: Would it be reasonable to implement other state space searches using tree-seq's basic interface?

16:55 e.g. a bfs tree-seq

16:55 iterative deepening tree-seq

16:55 a* tree-seq

16:56 hiredman: ~def tree-seq

16:56 X|

16:56 ,tree-seq

16:56 clojurebot: #<core$tree_seq__4588 clojure.core$tree_seq__4588@e40293>

16:56 hiredman: huh

16:57 ,#'tree-seq

16:57 clojurebot: #'clojure.core/tree-seq

16:57 hiredman: ,^#'tree-seq

16:57 clojurebot: {:ns #<Namespace clojure.core>, :name tree-seq, :file "clojure/core.clj", :line 2953, :arglists ([branch? children root]), :doc "Returns a lazy sequence of the nodes in a tree, via a depth-first walk.\n branch? must be a fn of one arg that returns true if passed a node\n that can have children (but may not). children must be a fn of one\n arg that returns a sequence of the children. Will only be called on\n nodes for whic

16:57 hiredman: ~def map

16:57 why no tree-seq love

17:01 ~def update-in

17:04 ,(.contains (rule-set #(or (> 3 x) (< 3 x))) 3)

17:04 clojurebot: java.lang.Exception: Unable to resolve symbol: x in this context

17:04 hiredman: ,(.contains (rule-set #(or (> 3 %) (< 3 %))) 3)

17:04 clojurebot: false

17:04 hiredman: ,(.contains (rule-set #(or (> 3 %) (< 3 %))) 2)

17:04 clojurebot: true

17:04 hiredman: ,(.contains (rule-set #(or (> 3 %) (< 3 %))) 4)

17:04 clojurebot: true

17:05 hiredman: ,(.contains (union (rule-set #(or (> 3 %) (< 3 %))) #{3}) 3)

17:05 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Boolean

17:06 hiredman: bah

17:08 durka42: (doc rule-set)

17:08 clojurebot: "([rule]); "

17:08 durka42: ~def rule-set

17:08 hiredman: http://paste.lisp.org/display/80355

17:09 the contains impl is broken

17:09 but the idea is to be able to define sets using rules

17:09 durka42: it's a good idea

17:10 hiredman: but there are issues

17:10 * durka42 wonders if the idea came from my bastardization of :inline the other day

17:11 hiredman: eh? there was talk about how arity information for functions could be implemented

17:12 so an arg list of [foo bar & baz] would be (rule-set #(> % 2))

17:12 durka42: ah, i see

17:13 Chouser: danlarkin: I don't know test-is very well, but I don't see a problem with that patch.

17:13 danlarkin: you have contrib commit privs?

17:13 hiredman: but how to print such a thing?

17:14 danlarkin: Chouser: I do, but my patch there is based on David Nolen's work... I don't know, does he need to be a contributor too?

17:14 hiredman: and rule-sets infect othersets, turning them into rule-sets

17:14 Chouser: danlarkin: he needs to have signed the CA, not necessarily have commit privs.

17:15 danlarkin: Chouser: oh, I see what you meant. In that case I do not have commit privs, I'm only a CA

17:15 Chouser: oh, ok. I was hoping you could just check it in. :-)

17:16 hiredman: ~ping

17:16 clojurebot: PONG!

17:16 danlarkin: dnolen_: submit your CA :)

17:16 dnolen_: heh :)

17:17 danlarkin: Chouser: I've gotta run just now, but thanks for taking a look

17:17 Chouser: ok, np

17:17 danlarkin: I guess when dnolen_ gets his CA in you can commit it

17:18 Chouser: dnolen_: let me know when that happens.

17:18 dnolen_: OK, will do that this week.

17:18 will do.

17:18 Chouser: thanks

17:18 danlarkin: thanks all

17:27 lisppaste8: hiredman annotated #80355 "fixed .contains" at http://paste.lisp.org/display/80355#1

17:27 hiredman: ,(.contains (union (rule-set #(or (> 3 %) (< 3 %))) #{3}) 3)

17:27 clojurebot: true

18:04 technomancy: so the first exception layer thrown by swank-clojure is *always* useless

18:04 (unless you're debugging swank-clojure)

18:04 clojurebot: clojure is the brand

18:04 * technomancy wonders how hard it would be to disable it

18:05 technomancy: or ignore it, rather

18:19 ctdean: is there an existing function like (best f coll) that picks the biggest/best item from a collection?

18:20 Chousuke: greatest-by in contrib IIRC

18:20 ctdean: great, thanks

20:11 unlink1: If you have (f (g (h (i x)))) and any of f, g, h or i might return nil in case of failure, what is the idiomatic construct for having the nil bubble up the entire call chain?

20:49 Chouser: unlink1: I don't know of anything built in. Pretty sure I saw a macro for that, though.

20:50 duck1123_: Is there any new documentation yet on the changes to the ns macro? I'm not seeing much on the ML and I'm still getting errors I never got before

20:50 Chouser: (and x (i x) (h (i x)) (g (h (i x))) (f (g (h (i x)))))

20:50 ?

20:51 dnolen: duck1123_: seems like it's safer to stick with the stable 1.0 release until things get ironed out.

20:52 unlink1: Chouser: yeah, but without the reevaluation

20:53 Chouser: well, your functions are all pure and memoizing, right? ;-)

20:53 unlink1: You may be thinking of defmacro- nilsafe

20:53 in clojure.contrib.core

20:54 (which is obviously unsuited here)

20:54 Perhaps some sort of monad-based solution is apt here.

21:00 duck1123_: Ok, I'm pretty sure I'm using 1.0 now, but I'm still getting java.lang.ExceptionInInitializerError, any ideas?

21:00 dnolen: did you do a fresh checkout of contrib and built it with Clojure 1.0?

21:02 duck1123_: I'm pulling the one from the maven repository @ http://tapestry.formos.com/maven-snapshot-repository

21:03 so it looks like it's 8 days old

21:04 I think I'm just going to stop using that one and build my jars locally

21:19 sh10151: Got an API design question --

21:20 can anyone see any issues with coding different traversal strategies using the same API as tree-seq?

21:20 e.g. BFS, and more complicated searches such as iterative deepening and A* ?

21:34 duck1123_: does anyone know what "Caused by: java.lang.NoSuchMethodError: clojure.lang.MultiFn.<init>(Lclojure/lang/IFn;Ljava/lang/Object;Lclojure/lang/IRef;)V" means?

21:34 I'm getting that from compojure

22:15 cads: I have created a semi-modular vector space system in clojure, and was wondering about fully modularizing it

22:18 I'd like have a function which takes a few user supplied basis functions and creates a system of derived functions, and binds them all in a new namespace, or something like that

22:19 bleh, I'm almost describing on object oriented kind of discipline :/

22:20 what's the idiomatic way of doing something like this in clojure?

22:26 slashus2: I noticed that if you use clojure-1.0.0-RC1-SNAPSHOT.jar with a clojure-contrib.jar compiled with the latest svn version of clojure you get an error when using some of the clojure.contrib methods.

22:29 cads: Should I use a struct to ecapsulate a system of functions: For example (defstruct vspace :n-vec :n-vec? :to-n-vec :dim :add :neg :sub :s-prod :dot :mag :l-k-norm :l-inf-norm :dist :l-k-dist :angle :cross-prod)?

22:30 Where each holds a ifn, but the function that creates these structs only requires a few of the ifns, and generates the rest

22:31 slashus2: Is there a good reason for the errors?

22:37 arohner: cads: I don't understand enough about your problem, but it does sound reasonable to use a struct or map to hold a bunch of fns

22:37 the only real difference between a struct and a map is that 1) the keys of a struct are shared, for memory usage reasons and 2) you can add new keys to a struct, but you can't remove the original keys

22:38 slashus2: a few contrib methods compile against clojure.core. a few days/weeks ago some internal APIs changed, so their api broke

22:39 slashus2: recompiling should fix the problem

22:40 slashus2: Just making sure the broken backward compatibility was okay. If that is actually what it is.

23:18 Qvintvs: does anyone see something wrong with this program: http://pastebin.com/m31bcb6d0 it's supposed to make a list of all the numbers it finds in the "test.in" file. it ends up giving me an empty list.

23:21 liebke: Qvintvs: it seems to work for me

23:23 stuhood: yea, works for me too

23:24 Qvintvs: what test.in files were you using?

23:25 liebke: I just used a rand png file

23:25 stuhood: ,(print "1\n2\n3\n4\n5\n")

23:25 clojurebot: 1 2 3 4 5

23:25 stuhood: er, you get the idea

23:27 Qvintvs: ah, wow, ok, I just wasn't looking for the output properly

Logging service provided by n01se.net