#clojure logs

2008-06-12

00:32jcriteshey... I just saw a neat presentation about Clojure
00:33jcritesI was wondering -- if I were going to convert some Java code to Clojure, how would I implement the visitor pattern? is there a better Clojure idiom?
08:12cgrandrhickey: wow, thanks for working on reduce
08:13rhickeycgrand - wait, let me check it in...
08:14rhickeyok, now up
08:14rhickeyreduce problem was a bug from my perspective
08:14cgrandcool, thanks
08:15rhickeybut I would caution that you beware the REPL itself can hold onto arg exprs, so when you want to test this, wrap in a let/fn/times or something
08:18cgrandok
08:18cgrandbtw I ran into the reduce problem while playing with Wide Finder 2
08:19rhickeyah, I've been meaning to look at that, glad you are
08:22cgrandI translated Bray's ruby script to Clojure nearly line by line -- it surprised me to not have to fully rewrite
08:23cgrandIt's certainly not the most idiomatic clojure code...
08:23rhickeyI fiddled with WF1 a bit, wrote about it in the group
08:24rhickeyI think Clojure's strength will be in the ease-of-parallelization area
08:24rhickeyhttp://groups.google.com/group/clojure/browse_frm/thread/7f2180bba2bb67c3/ca161d86b3d8045f?lnk=gst&q=wide+finder#ca161d86b3d8045f
08:24rhickeymany new features make that even easier now
08:25rhickeypre regex support
08:25rhickeypre destructuring
08:25cgrandyup, right now I have a parallel version which is the serial one with a pdoseq macro instead of a doseq
08:25rhickeythat is very cool
08:26cgrandbut it not performs pretty well on the T2000
08:26cgrand-> it doesn't perform
08:26rhickeywf1 wasn't very parallelizable
08:27rhickeyif you want input let me know
08:27cgrandyou still recommend to use agents to dispatch lines ?
08:28rhickeynot sure about the granularity, lines may be too small
08:29rhickeythere are 2 aspects to performance here - one is absolute perf, the other is speedup due to parallelization
08:29rhickeyif you get the latter, it's still a benefit
08:31rhickeythe former can be a sinkhole as people do block i/o etc
08:31rhickeyreally a waste of time
08:31rhickeybut should try to beat Ruby :)
08:31lisppaste8cgrand pasted "Wide Finder 2 (serial code)" at http://paste.lisp.org/display/62110
08:49cgrandthis code is already faster (but not that much) than Ruby: on my box for 10M lines I get 3'45" (Ruby) and 2'45" (Clojure)
08:51blackdogcgrand, is the regex compilation cached?
08:52cgrandafaik the compiler turns regex literals into constants
08:54cgrand(the constants being the compield java.util.regex.Pattern
08:54cgrand)
08:56blackdogok, that's interesting, so one doesn't need to re-pattern in advance then
08:59blackdogcgrand, is that jruby or cruby your testing on?
08:59cgrandcruby
09:09rhickeyblackdog: yes, regex literals #"..." are compiled on read
11:40Lau_of_DKAny body here got some experience with the 5 Guess Mastermind algorithm ?
11:48rhickeyLau_of_DK: please try to keep the dialog here focused on Clojure, thanks
11:50Lau_of_DKrhickey, I'm entering (or trying to) a 5 guess algorithm written in clojure in a contest - does that make it relevant ?
11:51rhickeyonly if related to the Clojure part
11:55Lau_of_DKrhickey, I understand that you want to keep it relevant - but this is one of the only places I get to hang out with Clojure coders, and everybody here code in Clojure so I imagine any general discussion about an algorithm would end up in actual code talk
11:55Lau_of_DKPersonally I would really enjoy it, if there were freedom for that kind of discussions, without keeping a tight censorship
12:18yrbis the (Class.) syntax to create a new instance only in the svn branch? and is a good idea to follow the svn or better to stick with releases?
12:19rhickey(Classname. ...) is svn only
12:20rhickeyI think many here track svn
12:25Lau_of_DKQuestions about the emacs stuff: When I start up swank clojure, I have 2 seperate REPLs running, one is *inferior-lisp* and one is *slime-repl clojure* - is this the same for you guyS?
12:38Lau_of_DKIf I do (recur (inc cnt) (take cnt fibs)) and cnt start on 1 - will this then take 2 ? Or is cnt not incremented until the loop restarts?
12:47Lau_of_DKnvm
14:12albinorhickey: watching the "clojure for java programmers", thanks lots of good info. One thing if I may make a suggestion, next time if possible can you restate the audience questions? Or maybe talk the hosts into giving audience member mics.
14:13rhickeyYes, I'm terrible with that... sorry
14:13albinorhickey: np, still way worth the time to watch
14:19rsynnottLau_of_DK: that's normal; you want to use the slime-repl one
14:19Lau_of_DKrsynnott, okay thanks - and yea thats what Im doing, just wondering why I had a second
14:22rsynnottI think the other is the lisp's stdin/out)
14:22rsynnottor the clojure's, in this case :)
14:23Lau_of_DKoh ok. One of the gabs in my "Lisp education" is that I never really found any good explanations of all the workings of emacs, slime, swank and all that. Got any good links? :)
14:24rsynnottnope
14:24rsynnottslime is more or less a link to the remote repl, with convenience stuff and a fancy inspector and so on
14:24rsynnottit uses data from the remote lisp to do indentation and completion and similar (which is very nice)
14:25rsynnottI wonder will someone do CUSP for Clojure? :)
14:25rsynnott(CUSP is a Java replacement for the Emacs bit of slime)
14:26Lau_of_DKrsynnott, thanks for the explanation, youre a link in your own right :)
14:27Lau_of_DKI'm not sure how difficult it is to build a editor/repl interaction, but not taking that into account, it wouldnt be a huge task writing a good IDE for clojure
14:30rhickeyhave you tried enclojure?
14:31Lau_of_DKYes, I've tried it
14:32rsynnottI've tried one netbeans UI for non-java-language before; it isn't an experience I'd care to repeat :)
14:32rsynnottI'm happy with SLIME
14:32rsynnott(it'd be nice to have an inspector and so on, of course)
14:33Lau_of_DKI never thought I'd say this, but I'm actually pretty happy with the emacs integration. If Enclojure gets a better interaction with the REPL and a few other details sorted out, I might switch to it though
14:33ericthorsenrsynott: what problems did you encounter? We are building the enclojure plugin for clojure. Have a REPL, code browser, debugging support, etc.etc.
14:34ericthorsenThere is still much work to do but Netbeans has taken care of quite a bit of heavy lifting.
14:34ericthorsenhttp://www.enclojure.org
14:36rsynnottI just didn't like netbeans very much, really :)
14:40Lau_of_DKericthor, can you evaluate single defn's directly to the REPL in Enclojure yet?
14:56Lau_of_DKIn C#, if I wanted "Bits" to become "Bitz" I could just do str[3] = "z" - Is there anyway I can do that operation from Clojure on a java string?
14:57Chouser_you want to mutate the string!?! ;-)
14:59Chouser_(str (.substring "Bits" 0 3) "z")
14:59Lau_of_DKYes Chouser, I have this one stupid assignment that I've spent an hour on now, its driving me crazy
15:00Chouser_(.replace "Bits" "s" "z")
15:05rsynnottassignment?
15:05rsynnottare you using this for college stuff or something?
15:06Lau_of_DKNo its just a project
15:07Lau_of_DKI'm trying to do a Mastermind puzzle solver
15:27rsynnottah
15:27rsynnottcool :)
15:27rsynnottI did one of those years ago... in C
15:27rsynnottyuk
15:27rsynnottno, actually, it was in turbo pascal :S
15:34blackdogjumping in, i have a start of a clojure plugin for jedit,
15:34blackdogit has a console and can run jedit macros, but i'm having difficulty evaling a buffer
15:35blackdogi'll post what i have if anyone is interested
15:38blackdogwell not evaling, but it doesn't seem to use the same classloader as the console, cos i can't find the vars in there
15:38Chouser_blackdog: clojure uses its own classloader
15:39rhickeybut that classloader is a child of the one used to load Clojure
15:40blackdogi'm not sure, i was going well, with clojure macros being able to populate the clojure console,
15:40blackdogwith stuff, but doing the same kind of thing by evaling the buffer didn't work, maybe slava will help :)
15:40blackdogjedit is his baby
16:36Lau_of_DKI have a long function that is throwing a Typecast error - Is there anyway I could get a linecount that fires this exception, instead of just 20 lines of java dump?
16:51rhickeynew release, new site up
17:00la_meroooh, shiny :-)
17:04la_merrhickey: regarding the license -- have you gotten any more feedback on it w.r.t. commercial *use* of clojure? (I'm remembering now the slight dust-up over the license some months ago on google groups)
17:05la_mer(FWIW, I agree with your interpretation of the CPL, I'm just wondering if anyone else has expressed concerns / disagreement with your interpretation)
17:10Chouser_Lau_of_DK: aren't there line numbers on each line of the stack trace?
17:11Lau_of_DKYes, but to files like boot.clj, swank-clojure.clj and so on
17:12Lau_of_DKI just want something like Cast exception: Line 5, Col 2, in my own file
17:14Chouser_Lau_of_DK: perhaps you can nopaste the function and stack trace?
17:14Lau_of_DKnopaste?
17:14Chouser_http://paste.lisp.org/new/clojure
17:17Lau_of_DKthanks, i'll get to a little later, I have to finish something before bed
17:26rhickeyla_mer: no complaints for commercial use. May be some GPL incompatibilities
17:28slavarhickey: nice site
17:28slavawhat CMS are you using?
17:31rhickeythat's wikispaces
17:31slavahopefully one day it will be something written in clojure :)
17:31rhickeyI guess, if someone's interested in that domain
17:37la_merrhickey: that's a plus, IMO ;-)
17:37slavawhy did you pick CPL and not BSD?
17:40rhickeybecause I want derived work to give back
18:01slavai rewrote your persistent-vector implementation in factor; is this code bound by the CPL?
18:01slavadoes a rewrite count as a derived work
19:20rhickeyslava: I think that depends on how much of a copy it is and how much original - it might
19:27slougihi. is there an example somewhere on how to use external java libraries from clojure? I'd like to play with using it in conjunction with Qt Jambi.
19:28rhickeyif they are in your classpath, you can import them just like built-in Java libs
19:29slougihow would that be? (I am not entirely fluent in Java)
19:29rhickeyhow to put in classpath or how to import?
19:30slougihow to import :)
19:30rhickeyparallel.clj, which comes with Clojure. imports the forkjoin library - you could look at that
19:31slougithanks for the pointer. and sorry for the newbie questions, i honestly didn't find a good answer before.
19:32slavarhickey: have you considered adding compile time type checks of any kind to clojure?
19:32rhickeya little bit - since I track types for reflection elimination
19:33rhickeyI like the idea of optional checks that generate warnings
19:36rhickeyslougi: doc for import is in: http://clojure.org/namespaces
19:45slougirhickey: cool, i missed that before. I was looking in java interop. thanks =)
19:50slougiwow, this is very cool
19:50slougithe first lisp that actually interacts with the toolkit i want to use in a decent way
19:52slavaclojure has a lot of potential, it is well-designed and it will hopefully get more people interested in lisp in general
19:52Ycrosoh wow, when did the site get a redesign
19:52slavamy interest in clojure stems from its use of persistent data structures and iterators. i don't care about java interop so much :)
19:52slougiit's the first lisp that i like the feel of to be certain
19:53njbartlettI want to call the Compiler.load method from Java, but I need to specify a classloader. Can I somehow put it into the LOADER static field?
19:53rhickeyYcros: redesign is still underway, but had to cut over with the release since that's where the new docs are
19:56rhickeynjbartlett: could you explain a bit why?
19:57njbartlettrhickey: OSGi integration. I want to compile some Clojure code contributed by a bundle, using that bundle's classloader
19:57rhickeyfor use only by that bundle?
19:58njbartlettrhickey: Not necessarily, the result could be shared
20:00njbartlettrhickey: Hmm I guess the clojure-generated classes are never going to form exportable API from that bundle, but instances could find themselves in other bundles as services
20:01rhickeyI know nothing about OSGi, but wonder how cross-sibling sharing works, normally couldn't be seen
20:02njbartlettOSGi doesn't use hierarchical classloaders. Instead they're arranged in a graph, with explicit imports and exports of Java packages
20:04rhickeyThe classes Clojure generates on the fly should never be seen directly by name, only through interfaces in the Clojure libs, e.g. IFn
20:04njbartlettBut just thinking aloud here... to be able to write exportable classes in Clojure, I would have to get the compiler to generate a class from a clj in response to a class load event, which means I need a special classloader
20:04njbartlettrhickey: Hmm but you can generate interface instances as dynamic proxies right?
20:05rhickeyexactly - I can;t depend on the supplied classloader's ability to load bytecode from memory - I must create my own - but could parent from supplied loader
20:05njbartlettRight that's what i need to work out, how to supply you a parent classloader
20:05rhickeyinterface instances yields instances of the interfaces, at least with proxy, so there too name is not exposed
20:05njbartlettI assume your classloader does normal parent-first delegation
20:05rhickeyit does
20:06rhickeyI sued to use the context classloader, which would have given you a way...
20:06rhickeyused
20:06njbartlettRight. But now?
20:07rhickeynow it's hardwired to RT.ROOT_CLASSLOADER
20:07rhickeyyou could, as an experiment, make that non-final and set it temporarily to try your idea
20:08njbartlettUhuh. I was already thinking this wasn't going to work without submitting back patches
20:08rhickeylet's see if it works at all first. I'm willing to work on making this hookable
20:09njbartlettBTW my codename for this little project is Closgiure :-)
20:09rhickeyyikes
20:09rhickey:)
20:10rhickeyI think there are some fundamental conflicts between these graph-like classloaders (and need to re-parent all the time) and gen-and-load-class
20:10njbartlettSo ROOT_CLASSLOADER is static, like everything else... that means if I set it temporarily I can only compile in a single thread
20:11rhickeyyou can try it out and I can make it thread-local with vars
20:11njbartlettOkay
20:12rhickeyif you see compiler.load does a lot of that already
20:13njbartlettYeah I'm just trying to get my head around your, um, unorthodox Java coding style!
20:14rhickeyI still question why you need to use that other classloader
20:14rhickeywhat happens if you don't?
20:17njbartlettSay the Clojure code imports package org.foo. That package will be visible to the containing bundle because it imports org.foo at the bundle level, but it won't be visible to the Clojure bundle itself. Essentially I want to make a Clojure bundle that performs a "compilation service" for other bundles.
20:17rhickeyI don't think that is sound
20:18njbartlettOkay, I don't know enough about Clojure yet. It's an experiment.
20:18rhickeyClojure is a compiled language, whose compiled named entities are static and global (per classloader), just like Java's
20:19rhickeyi.e. there's no difference between clojure/rest and Math.max
20:19njbartlettRight, but your compiler is executed at runtime
20:19rhickeydoesn't matter, it's atill trying to obtain compiled performance, so names must be bound, not looked up every time
20:20rhickeyagain, like Java, code that uses Math.max gets linked/bound once to a global entity
20:20njbartlettWhat do you mean, names must not be looked up every time?
20:21rhickeyThe alternative to my unorthodox static style is to put names in instance environment objects in which things are looked up
20:21njbartlettWell no it doesn't. Somebody asks their classloader to load the Math class, and that gets delegated up to the boot classloader, and then the static method if invoked.
20:22njbartlettIn theory there could be an alternative implementation of Math. Actually not because of a special rule (only the boot classloader is permitted to define classes in the java.* namespace)
20:22rhickeyonce only, it's not looked up every time, and it's looked up in a global place
20:22rhickeyper classlader
20:22rhickeyclassloader
20:23njbartlettRight, I don't see what this has got to do with my approach to integration with OSGi
20:24rhickeyHaving one Clojure and many unrelated classloaders puts the onus on Clojure to work like OSGi
20:24rhickeywhich provides some non-hierarchical sharing
20:24njbartlettI don't believe it does
20:25rhickeylet's set the class part aside. If you load some fn ns/foo, that is globally available to all modules using the same Clojure
20:26rhickeyWhich wouldn't conflict with the Java hierarchical model, since they would all be beneath whatever loaded Clojure
20:26njbartlettAh I see what you mean about the sharing your do
20:27njbartlettHow do you make these things visible? It's clearly not just via classloaders
20:27rhickeyit kind of is ,since I use Java's static semantics
20:28njbartlettRight but you assume you always have the same parent classloader
20:28rhickeyso the module that loads Clojure is like Clojure's version of the System classloader
20:29rhickeyit's a root for everything running under that Clojure
20:29njbartlettI see.
20:30rhickeyusing statics ensures that if you loaded a second Clojure under another clasloader, it would be independent
20:30rhickeycompletely
20:30njbartlettOkay, I have tried separate instances of Clojure, one per bundle, but it's just too damn slow for that.
20:30njbartlettLike 5 seconds startup time
20:31njbartlettFine if you're only doing it once for the whole JVM...
20:32rhickeythen I would say that you need to take a different approach to modularity for using a shared Clojure than classloaders - using Clojure's namespaces for instance, because the OSGi separate classloaders aren't really giving you any isolation in this case
20:32njbartlettRight. In other words, Clojure doesn't add any value to OSGi and vice versa. Or so it seems.
20:34rhickeypossibly not, but with understanding of how it works we might be able to address your objectives in using OSGi
20:35rhickeybecause you certainly can share an instance, and Clojure has very good thread independence
20:36rhickeyand namespaces
20:36njbartlettI'm committed to OSGi so the question for me is whether Clojure can be useful to me in that environment.
20:37rhickeyI've talked with people using NetKernel about using UUID named tear-off namespaces
20:37njbartlettRight I followed some of that thread
20:38rhickeyyour loader service could load code in a guaranteed unique namespace, and deliver IFns to consumers, dropping the ns after load
20:40njbartlettI'm going to have to learn more about Clojure and come back to this. I think I've come at it with some invalid preconceptions from doing Scala etc
20:41rhickeyfeel free to follow up on the group
20:41njbartlettWill do, thanks
20:49Chouseror something.
20:52rhickeyruby?
20:54Chouseryep. on rails. It was my choice as or a year or two ago. Now I have to live with it.
20:55Chouser"as of"
20:55rhickeywould you want a full-stack rails-alike for Clojure?
20:57Chousernot sure. The main benefit I was hoping for from Rails was an architecture with pluggable features.
20:57Chouserneed a user authentication system with email-reset of password? plug it in. that sort of thing.
20:58ChouserIf properly done, I would think a modular (non-full-stack) system could allow for that.
20:58Chouser...and in practice, rails doesn't even do a particularly good job. "plug it in" includes generating code in your app source tree, which rather complicates upgrades.
20:58dudleyfChouser: Have you looked at Merb?
20:59dudleyfI'd like to see something more like that for Clojure
20:59dudleyfWorking with ActiveRecord has made me hate ORM, too
20:59ChouserI haven't done enough of this kind of app to know how to design an API that cuts across at the "right" places. I was hoping Rails would be an easy way to import that kind of expertice, but I'm not overly impressed.
21:00ChouserI've always been a bit cold to ORM. If I knew of a good replacement for the relational database, I'd definitely look into that.
21:00Chouserdudleyf: peeked at it, but it's way too late now.
21:01rhickeyheh, I think the problem is the O part
21:01dudleyfI like the database part, It's the objects that bother me
21:01rhickeynot the R
21:01dudleyfHeh, yeah
21:01rhickeyI've done OODBMS, no mapping, it was not a good experience
21:02Chouserthey both seem a poor fit. My data doesn't really fit neatly into tables, and after forcing it there both I have to work pretty hard to express what I mean, and the DB has to work pretty hard to make it performant.
21:02dudleyfI don't have much experience with JDBC, is it possible (easy) to get back something that looks like a seq of maps?
21:02rhickeythat can happen too
21:02JamesIrydudleyf: that would be very easy
21:02Chouserhm, not having ever used an OODBMS I thought maybe they were the Solution.
21:02dudleyfChouser: CouchDB?
21:02rhickey(doc resultset-seq)
21:03JamesIrydudleyf: JDBC result sets are more or less the Java equivalent of seq of maps
21:03Chouserpeeked at that too.
21:03Ycrosactiverecord is the worst part of rails (I'm also a rails developer)
21:03dudleyfThanks
21:03rhickeyThe problem with OODBMS is that information is not objects
21:03JamesIryFor a completely alternative way to interface to a SQL DB, see also HaskellDB. Probably not appropriate for a dynamically typed language, though.
21:04rhickeyit can be sliced an indefinite number of ways
21:04Chousertuplespace
21:04rhickeybut an OODBMS bakes an applications view of the data in to the data
21:04ChouserI've been flirting with RDF too.
21:05Chousersee, this is part of why I picked rails -- I wasn't confident enough in any particular alternative. Oh well. For now I just have to live with it.
21:05Chouser...learn as much as I can about what I would really want.
21:07Ycrosmerb is actually a lot better
21:08Ycrosit has cleaner code, less magic, runs faster, uses less memory
21:08Ycrosand it doesn't tie you down to activerecord
21:08Ycrosof course, you do lose the ability to simply drop in a lot of rails plugins (some of the more generic ones still work)
21:09dudleyfrhickey: Do you have large projects in Clojure?
21:09rhickeyClojure is a large project
21:09rhickeyNot yet, starting to use it in my work
21:09dudleyfWell, right :-)
21:14dudleyfAre namespaces enough to keep the various modules of code separated from each other in a large project?
21:14rhickeyworks for JAva
21:15dudleyfBut Java has classes as well as packages
21:16rhickeyand lots of the functions in those classes are getName/setName etc, not even needed with maps
21:17rhickeynamespace names can be multi-component as well, so you could go one level further to mimic class scope
21:19blackdogrhickey, how does that work? multi-component?
21:20rhickeyfoo-bar-baz/fred, or foo.bar.baz/fred
21:20rhickeyjust convention
21:20blackdogok