#clojure logs

2008-06-04

01:54albinothis? http://vim.sourceforge.net/scripts/script.php?script_id=221
02:03Ycroscould be. I should have bookmarked it
02:05Ycrosactually no, I think it was Limp (which is linked to from the one you found)
10:49Chouse1after I picking that little fight yesterday, I lost track of one of my initial questions...
10:49Chouse1Is it better to use (. Class forName "org.postgresql.Driver") or (. java.sql.DriverManager registerDriver (org.postgresql.Driver.))
10:50Chouse1...or is there a better way altogether?
10:53rhickeyI didn't get time to look at why simply naming org.postgresql.Driver was insufficient. But I kind of dislike Class forName - I'd go with the latter
10:53rhickey(even in Java I've encountered this with JDBC drivers)
10:54rhickeythere is also more of a declarative, preferences-based registry I think
10:54Chouse1Ok. I hadn't seen any examples doing the later. I didn't know if there might be bad side effects or consequences.
10:54rhickeythe whole thing is built on the driver self-registering as a side effect of loading - ugh
10:55Chouse1yeah. I'm sure whoever made it up thought it was rather clever.
10:56rhickeyfrom the DriverManager docs:
10:56rhickeyAs part of its initialization, the DriverManager class will attempt to load the driver classes referenced in the "jdbc.drivers" system property. This allows a user to customize the JDBC Drivers used by their applications. For example in your ~/.hotjava/properties file you might specify:
10:56rhickey jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver
10:56rhickey
10:56rhickeymight be a better approach
10:57Chouse1ok
13:02Chouse1I just wrote a proxy that maps a vector of vectors to an AbstractTableModel.
13:03Chouse1About half of the Clojure method bodies are fewer characters than the Java method names.
13:03rhickeyheh
13:03Chouse1(getColumnName [i] (nth cols i))
13:04rhickeydoing some Swing?
13:04Chouse1I am. First time, really.
13:04Chouse1also first time using java.sql, as yesterday's outburst indicated.
13:04rhickey:)
13:06Chouse1Using doto, I can build up a swing widget tree using code that mimics the hierarchy pretty well, and without naming most of the intermediate panels.
13:06Chouse1...which is pretty nice. The Java examples I'm looking at quickly become a tangle of awkwardly named local vars.
13:07rhickeyusing (JThis. ...) makes that pretty declarative too
13:08Chouse1Yeah I converted all my (new...)s to (JFoo. ...)s this morning. I'm still pretty ambivalent.
13:08Chouse1I think if I had my syntax highlighter pick out the JFoo.'s in a different color, that might make the difference.
13:08rhickeyGroovy has 'builders' for Swing just for that, Clojure comes close with no special support
13:08rhickeyhighlighting would be excellent, yes
13:10la_merHas anyone really pushed around enclosure yet?
13:10Chouse1btw, I wrote my own result-seq because I needed a vector for each row instead of a struct map. With (.method obj) and #() syntax, is significantly shorter.
13:11Chouse1sorry, resultset-seq
13:11Chouse1la_mer: I'm meaning to, but haven't yet. I get the impression the creators are using it pretty heavily.
13:11Chouse1lunchtime.
16:23Chouse1for clojure to work in javascript, you might not need a lispreader in js, but surely you'd at least need the compiler, wouldn't you?
16:23Chouse1otherwise how would (eval) work?
16:27rhickeyIt depends, no eval is distinctly possible
16:29Chouse1as in, clojure might work even if it didn't have eval?
16:29la_merwow, gen-class is a whopper
16:29la_merincredibly cool, though :-)
16:30rhickeythere are 2 distinct ways to think about ClojureScript, one is a Clojure interpreter in JavaScript, the other is a compiler from Clojure to JavaScript (written in Clojure, and doing macroexpansion there)
16:32Chouse1right. They would have distinct feature sets or usage profiles, right?
16:32rhickeyI think a Clojure (subset) to js compiler is more interesting then sending Clojure code to the browser for interpretation, YMMV
16:33Chouse1that would mean some kind of (to-js) function or macro that consumes a file or clojure code/data structures and produces a string, right?
16:34rhickeyyes
16:34Chouse1someone mentioned starting that already.
16:34Chouse1cgrand
16:35Chouse1http://clojure-log.n01se.net/date/2008-05-29.html#17:56
16:35rhickeythere are js correlates for many of the special ops, then just do macroexpansion on the clojure side to get more language, plus something like the Java syntax for talking to the js stuff
16:36Chouse1I'm trying to think if there are any features I think are really useful that would require a compiler/interpreter on the js side.
16:36rhickeya very early Clojure prototype was written in CL and emitted js
16:37rhickeythe thinking then was that js could be compiled in both java/.net, but .net's jscript had too many small differences
16:38rhickeybut a small lisp->js is pretty easy.
16:40rhickeyinteresting quote here: http://bc.tech.coop/blog/030920.html
16:41rhickey"Those of you who are familiar with more traditional functional languages, such as Lisp or Scheme, will recognize that functions in JScript are fundamentally the Lambda Calculus in fancy dress. (The august Waldemar Horwat -- who was at one time the lead Javascript developer at AOL-Time-Warner-Netscape -- once told me that he considered Javascript to be just another syntax for Common Lisp. I'm pretty sure he was being serious; Waldemar's a
16:41Chouse1that got cut off, but I've heard it elsewhere.
16:42Chouse1In fact, I'm pretty sure I've seen posts from the guy who started JavaScript that he was hired to create a "scheme with Java-like syntax"
16:44Chouse1http://weblogs.mozillazine.org/roadmap/archives/2008/04/popularity.html
16:44rhickeycross-compiling Clojure is very doable. I compiled to both Java and C# for a long time. The only thing that doesn't map well is blocks (do) as expressions - if only the had kept C's comma operator!
16:45rhickeyand loops as expressions
16:45Chouse1"Whether that language should be Scheme was an open question, but Scheme was the bait I went for in joining Netscape"
16:46Chouse1developing code for use in the browser would either require a compilation step, or clojure running in a server.
16:47rhickeyI imagine most Clojure web apps would have Clojure running in a server
16:47Chouse1I suppose if you had the latter, you might with some effort be able to load updated functions without reloading the whole app in the browser.
16:47rhickeyas cgrand is doing, js and html gen could happen together
16:48rhickeymost of the servlet containers have comet support now
16:50rhickeyfunny, this just came by - ecmascript 4 to js compiler written in server-side Python:
16:50rhickeyhttp://ecmascript4.com/
16:51Chouse1huh.
16:54rhickeyI think the important thing that makes the Clojure->js job small is that the macros get expanded by and in Clojure, so you never have js versions of cond, when etc, just if
16:54Chouse1I assume cgrand is just writing functions to do the conversion. Any reason to think that's not the best way?
16:55la_merrhickey: Am I right in thinking that, assuming each namespace has appropriate metadata lined up, that gen-and-save-class could be used to dump a pile of loaded clojure to disk?
16:56rhickeyla_mer: no, the Clojure code behind a gen-ed class is not in the .class file, just the stub
16:57rhickeyCompiled Clojure code can have data literals in it, more complex to pre-compile.
16:58rhickeyat some point I might look at an ahead-of-time compiler
16:58la_merAh, that's why I'm getting "UnsupportedOperationException: XXXX not defined" when I try to load up the generated class -- it's not finding a matching .clj file to load the impl's from.
16:59rhickeythe impl can be loaded pretty late, but must be before it's called
16:59rhickeycan also be changed after objects exist
17:00rhickeyChouser: I haven't looked too closely at cgrand's js stuff
17:01rhickeybut bringing up a Lisp is always the same - a handful of special ops to bootstrap
17:02Chouse1right, I'm wondering if you think implementing the conversion in macros and clojure funcs would be better or worse than some other option, like an alternate Compiler class.
17:04la_merYeah. I just caught wind of the gen-and-save-class utility, and thought that perhaps it would enable source-less distribution.
17:04rhickeyChouser: ah, well, certainly not a Compiler class in Java
17:05Chouse1:-) You would have written yours in clojure if you could have, would you.
17:05rhickeydefinitely, it was always a hope to bootstrap it, but practically, once you have a working compiler, you're pretty tired :)
17:06Chouse1heh
17:07rhickeyTake the Clojure time machine: http://clojure.svn.sourceforge.net/viewvc/clojure/trunk/src/lisp/clojure.lisp?view=markup&pathrev=85
17:08Chouse1hm, looks like CL ;-)
17:08rhickeyCL to Java/C# compiler for an early Clojure
17:11rhickeyI don't think you'd need a full Clojure in js, but the ability to gen js from sexprs with macros would be really nice
17:13rhickeyso you use macros to get a tree of special ops, then walk the tree and emit js
17:13Chouse1I've written quite a bit of js (we've got over 38K lines for our project at work), and I'd be pretty frustrated if the environment were crippled or any less dynamic than js is by itself.
17:14Chouse1yeah, that doesn't sound too hard, does it? I wonder how far cgrand has gotten.
17:14rhickeywow! 38k
17:14Chouse1yeah, scary, right?
17:15Chouse1that doesn't include the 3rd-party libs we use (zimbra, google maps, openlayers, etc.)
17:15rhickey keeping all of the js goodness would have to be a focus
17:15rhickeybut you'd take the same approach as with the Java - define minimal syntax support for direct calls
17:16Chouse1I guess one question would be -- how much would the data consumed by js* have to look like clojure source?
17:16rhickeydo you eval your json?
17:16Chouse1yeah, but that could stay json.
17:17rhickeythen either way, I think a js reader for Clojure data format wouldn't be too much
17:17rhickeyor translate to json at the gateway
17:17Chouse1you'd want js* to understand literal hash and vector syntax of course, but it clearly wouldn't need to do sync or agents.
17:18Chouse1...so would it need persistent data or not?
17:18rhickeyright, there isn;t a need to bring semantics to js it doesn;t already have
17:18rhickeyI don;t think persistent
17:18Chouse1I guess the clojure idioms might start to break down if you have js arrays instead of vectors. ...not sure.
17:19rhickeydepending on your data size you can just copy on write
17:20rhickeybut it is an issue for Clojure idioms
17:21Chouse1I don't think having conj modify an existing array would be acceptable, for example. If you wanted to do non-persistent you'd have to use a different verb.
17:21rhickeyyes, definitely
17:21rhickeybut Clojure has aset for Java arrays
17:22Chouse1ah, good point.
17:22Chouse1but being forced to use aset all the time would be painful.
17:22rhickeythe main problem is data size - copy on write preserves the semantics but doesn't scale
17:22rhickeybut you may not need to scale
17:23Chouse1...so I think that answers it (in my mind anyway) -- we'd need *some* kind of immutable list and hash on the JS side.
17:23rhickeylist is easy
17:23Chouse1right, it might not need to scale, but it'd have to be there in order for it to feel anything like clojure.
17:24rhickeyjs has everything you need to implement the hash map
17:24rhickeyjust arrays
17:25Chouse1hm. It'd be interesting to port hashmap to clojure so that it would work in js.
17:25rhickeyClojure leans heavily on Java's good ephemeral memory handling, not a known attribute of js
17:25Chouse1yeah, but again that mainly has to do with scaling. ..and the JS VMs will keep getting better.
17:26rhickeyI think you'd write it by hand in js and preload is as runtime support
17:26Chouse1why?
17:27rhickeybecause you don't have a Clojure->js compiler yet
17:27Chouse1but you could have a COW vector to get you by... ;-)
17:28Chouse1or even just JS array support.
17:28rhickeyobject models
17:29rhickeyI'm not arguing against it
17:29rhickeyJust that, I would have had to have had Clojure very far along in order to have it generate PersistentHaspMap
17:30rhickeyymmv
17:30Chouse1hm. Yeah, I guess the JS situation isn't any further along than you would have been with the Java version.
17:31rhickeyIt depends a lot on what the js would look like - functional or an object?
17:32Chouse1which in my experience hinges mainly on whether you want to use JS inheritence. If you don't need inheritance, closures are great for creating objects.
17:33Chouse1gah!
17:33rhickeyIt leverages Java, as I think it should given the layer it is at.
17:33rhickeywhen in Rome
17:34Chouse1what's missing?
17:34Chouse1I guess the flip side is having created hashmap in the host language, you can use it outside of clojure if you want.
17:35rhickeyclasses with typed fields, primitive bit math, static methods
17:36rhickeyyes, the Clojure Java lib has utility outside of Clojure, and can leverage all kinds of things I don't intend to add to Clojure
17:36rhickeylest Clojure inherit the complexity of Java
17:37Chouse1but that's because it's a Java class. surely that kind of functionality could be designed for and implemented in clojure.
17:37Chouse1if not, then isn't that a problem?
17:39rhickeyno, because in order to make a language go all the way down and match the efficiency it has to have primitive types
17:39rhickeythat was no to - isn't that a problem
17:40rhickeyyes you can implement abstractions like that, but they will have some cost due to their higher-level nature
17:41Chouse1oh, ok.
17:42Chouse1As long as the barrier is performance and not expressiveness, I'm ok. ;-)
17:43rhickeyI think Clojure holds it own on expressiveness
17:44Chouse1yes
17:44rhickeyOTOH, I'm pretty stunned that I was able to get the primitive math as fast as Java without emitting math primitive bytecodes
17:45Chouse1It feels a little odd to have to use java interop (proxy, gen-*-class) to create data structures that have compatible APIs with the buildins, but I guess that makes sense in light of your performance statement.
17:47rhickeya big benefit of that is that the resulting thing is native. virtual method dispatch is also very fast. Some other JVM dynamic langs interpose a wrapper/bridge class between everything
17:47rhickeyto map to their object models
19:24rhickeyChouser: what's the time for this on your machine:
19:24rhickey(loop [acc (double 0) ind (int 0)]
19:24rhickey (if (== ind (int 100000000))
19:24rhickey acc
19:24rhickey (recur (+ acc
19:24rhickey (. java.lang.Math (sqrt ind)))
19:24rhickey (unchecked-inc ind))))
19:24rhickeyvs what you posted?
19:28Lau_of_DKAnybody know what the reason for implementing primitive support in Clojure was?
19:28rhickeyspeed
19:29rhickeysome of us do audio/image processing
19:29rhickeynice to stay in Clojure
19:30arbschtavoids the "glue language" trap neatly
19:30Lau_of_DKoh - I just heard a talk you gave, rhickey, to a group of Lispers from NYC and just near the end I heard the sentences "there will never ever be primitives in Clojure" ?
19:31rhickeyand there aren't, really. It doesn't generate the bytecodes for primitive arithmetic itself
19:32rhickeyIt isn't something I expected to work this well. Never say never I guess :)
19:32Lau_of_DKAlright, thanks for clearing it up :)
19:32Lau_of_DKGood talk though - You got quite the applause
20:01Ycrosrhickey: hey, I saw an IRC log of you saying that Clojure doesn't need conditions/restarts because it can be implemented using dynamic function binding?
20:02Ycrosrhickey: is there something I can read, or can you shed some light on how this might be done?
20:03rhickeyhttp://groups.google.com/group/clojure/msg/842e8bb058015282
20:03Ycrosthanks :)
20:04rhickeysure. note I said similar, not exactly CL conditions
20:05Ycrosoh I see, that's fairly simple
20:05rhickeysimple meaning easy or simplistic?
20:10Ycroseasy I guess
20:11rhickeyyou can build richer abstractions on that if needed
21:26Chouserah, I was trying to use a primitve ind, but was missing the comparison literal.
21:28Chouserbut still, my posted loop ranges from 3132 to 3293 msecs, while rhickey's with unchecked-inc ranges from 3121 to 3293
21:37Chouserrhickey: you missed my answer, and nothing else.
21:37ChouserI had tried to use a primitve ind, but missed the comparison literal.
21:37Chouserbut still, my posted loop ranges from 3132 to 3293 msecs, while yours with unchecked-inc ranges from 3121 to 3293
21:38rhickeyunchecked-inc doesn't matter, but I think declaring ind int does - yours went from 5secs to 3.5 here
21:39Chouseroh! hm. I wonder why the difference between the improvement here and there.
21:40Lau_of_DKthis might be a really dumb question, but is the swank-clojure any different from a regular swank ?
21:43rhickeyChouser: I don't see how they could be the same speed - hmmm....
21:44rhickeysince both the compare and the inc have to be generic without the hints
21:44rhickeyare you java 6?
21:46Chouserright. When I tried (int 0) for ind but forgot (int 1000...), the performance was worse, I assume because of extra boxing and unboxing.
21:46rhickeyyou are on java 6?
21:48ChouserI think so. I'm trying to verify that.
21:49rhickeyjava -version
21:49Chouserah. yeah, 1.6.0-b09
21:50rhickeyinteresting. I'm stuck on 1.5, I've heard the optimizations are much better on 6, looking forward to that. I guess the main point from the benchmark was that Clojure is the fastest ;)
21:51Chouser:-)
21:51rhickeyTo be fair I think Kawa supports some hints that would make it faster
21:52rhickeyAnd I'm not sure that is the maximum opt from SBCL
21:52Chouseryeah, it's hard to be fair in a comparison like that without knowing each language pretty well.
21:52rhickeybut Clojure should always be == Java in this area now, which means plenty fast
21:52ChouserI thought a C version might be interesting.
21:53Chouserfor some value of interesting.
21:53rhickeysqrt is bad, some arithmetic would be better
21:53rhickeyrms or something
21:54ChouserJava's sqrt is bad, or what?
21:54rhickeysqrt is not primitive arithmetic
21:54Chouserah, true.
21:56rhickeyand dominates his benchmark
21:56rhickeyfyi, from REPL:
21:56rhickey (-> System .getProperties (get "java.runtime.version"))
22:01Chouserthanks
22:04Chouser(reduce + (map #(. java.lang.Math sqrt %) (range 10000000)))
22:06ChouserThat's just hopeless, isn't it.
22:06rhickey2.1081849486439312E10
22:07ChouserIf I replaced #() with something defined using definline, range would still be returning boxed numbers, right?
22:07Chouserand + would be generic?
22:12Lau_of_DKrhickey, what are the terms for building commercial software off clojure?
22:14rhickeyChouser: takes 4 secs here
22:15Chouseryeah, it's 1/10 the benchmark. sorry for the confusion
22:16Chouser10000000 instead of 100000000. how could you have missed that? ;-)
22:16ChouserLau_of_DK: http://clojure.org/license.html
22:16rhickeysorry, doing 2 things at once here
22:18Lau_of_DKThanks Chouser :)
22:20rhickeyChouser: laziness in map will dominate:
22:20rhickey(time (reduce #(+ %1 (. java.lang.Math sqrt %2)) 1 (range 10000000)))
22:24Chouserthat's still 898 msecs instead of 327 msecs for the loop version.
22:29rhickeyI consider that pretty good, considering range is a seq abstraction
22:31Chouseroh, sure! I'm not saying it's bad, I'm just kicking around with more idomatic forms.
22:38rhickeythe cool thing about the primitive math is that it is amenable to being the target of higher-level macros, like amap and areduce
22:39rhickeyI can imagine whole DSLs for different formula-building patterns
22:39rhickeybut it will be macrology, the higher-level constructs have some fixed costs
22:44rhickeyand 10 million steps of reduce and range in a second is fine perf for most apps. Only serious crunchers need get into this micro-optimization
22:44Chouseryep, good point.
22:45JamesIryrhickey: This is somewhat off topic of Clojure the language and more about its implementation. I've been reading papers on various STM impls lately. I remember you writing that Clojure uses MVCC. Do you have any links about the kinds of workload that MVCC based STM is good or not good for? Or has there even been any research into MVCC STM?
22:47rhickeyJamesIry: I read a bunch of papers on STM while I was designing Clojure's. They all left me wondering a bit about the context of use...
22:48rhickeyi.e. they seemed to focus on dropping STM under otherwise mutation-oriented apps...
22:48rhickeyfine grained field-level refs...
22:48JamesIryAgreed. Many of the benchmarks they user are hashtables or arrays where everything is a mutable ref.
22:48JamesIrys/user/us
22:48rhickeywhile I always was thinking about refs to immutable persistent data structures, more of a record orientation
22:48JamesIrys/user/use!
22:49rhickeyso turned to databases for inspiration
22:49rhickeyas I consider STM to be the same problem in many ways
22:49JamesIryVery much so!
22:50rhickeyspent lots of time with Gray and Reuter's "Transaction Processing"
22:50rhickeyand whatever info I could get on Oracle and Postgresql
22:53rhickeyI wasn't aware of another MVCC STM when I did my work, but this came up recently:
22:53rhickeyhttp://www.esw.inesc-id.pt/~jcachopo/jvstm/
22:53JamesIryI think it would be interesting to investigate the kinds of workload where the overheads of MVCC are small compared to the overheads of redoing the work, vs where the overhead is large. One interesting possibility is to have a pluggable STM impl so that application writers could do their own perf testing to determine which fits best.
22:54JamesIryThanks for the link
22:55rhickeyafter reading Gray and Reuter I would never want anything other than MVCC, in an STM or a DBMS
22:55JamesIry:)
22:55rhickeynot that they advocate it, my own conclusion
22:55Lau_of_DKrhickey, "never" ?
22:55rhickeyfor some value of never
22:55JamesIryYeah, how 'bout a very low contention scenario
22:56rhickeyI just don't see where MVCC loses
22:56rhickeylow contention everything works well
22:57rhickeyGray and Reuter do show some serious disdain for optimistic concurrency
22:57rhickeyThat's why Clojure has real blocking
22:58JamesIryOne paper I've been studying (http://www.cs.rochester.edu/~vmarathe/research/papers/2008_PPoPP.pdf) has an algorithm specifically optimized so that low contention is cheap. It's C based, though, and may be too expensive to translate into JVM terms.
23:01rhickeywill read, thanks
23:01JamesIryThe central part is based on 64 bit CAS - and that's not something that you can rely on being reasonable on every JVM
23:03JamesIryI'll have to pick up the Gray and Reuter book
23:03rhickeyI have a philosophical problem with allowing more work to proceed than can succeed
23:04JamesIryrhickey: I hear you. It's okay if the work is cheap compared to the costs of blocking...but at the datase level that's almost certainly not true. When dealing with in memory refs to large immutable structures it probably still isn't true.
23:05JamesIryThat's one problem with the benchmarks that many STM papers use. They pound the hell out of the refs, but few actually do much work in between reads and writes.
23:06rhickeyI just see no correlation to the reality I;ve experienced writing MT programs in those papers
23:06JamesIryIt's a classic microbenchmark miopia.
23:06rhickeyFor me, STM is a way to automate and make correct the same kind of locking that would be done manually in a real program
23:07rhickeyfor super-contended caches the stuff Cliff Click is doing will work fine, I wouldn't try to do that with STM
23:07JamesIrySure...but in some cases doing CAS and retries makes sense when you do things manually.
23:08JamesIryYeah...his stuff is definitely the kind of thing where special purpose constructs like concurrent maps make more sense.
23:08rhickeyhe's in the CAS world
23:09rhickeythere's likely no one-size-fits all
23:10JamesIryThat's why it would be interesting to see a suite of benchmarks againt various STMs. Some benchmarks could do real work so that there's a cost to any retries. Others could just pound crap out of the refs so that blocking itself becomes a major overhead.
23:11JamesIryUsers and designers of STMs could then evaluate which work load is more nearly like their own - or, as I was thinking earlier, empirically try several impls.
23:12rhickeyIt's an area (realistic benchmarks) that needs attention
23:13JamesIryOne thing I'm excited about is languages like Clojure taking concurrency seriously as a first class concept.
23:14rhickeyIt's got to be more than an add-on or it won't work. I don't think people can just drop STM into the same old approach. Immutability has to be taken seriously, for instance
23:15JamesIryAgreed.
23:16rhickeyI would hope Clojure offers a model (persistent data structures in refs) that is compatible with it's STM approach
23:16JamesIryIt's going to be a learning curve, though. It will take a while for people to wake up from the illusion that state can be encapsulated.
23:17JamesIryThe only way to encapsulate state is to limit the scope of what it can possibly affect - OO doesn't do that at all well. The state of one object affects the transitive closure of all objects with references to it.
23:18rhickeyA recent thing I added to Clojure allows you to make Java objects whose state was a ref - transactional objects if you will. Still thinking through the implications...
23:19JamesIryNot sure I follow
23:19rhickeythe problem with OO is the direct references to mutable things. Making them indirect and transactional, to immutable things, can let it feel quite similar while ensuring that people can only ever see consistent objects, without needing locks
23:19JamesIryI got ya
23:24rhickeyone of the nice things about using a ref to an immutable map, say, for an object's state, vs a bunch of fields each of which was an STM ref, is that you can, outside of a transaction, get a consistent object
23:27JamesIryYup. The context in which I've been exploring STM is to create one for Scala. Scala's story on immutability isn't as good as Clojure's, though. It's got immutable persistent structures in the standard libary, but it doesn't really discourage mutable objects either. So I forsee much trouble with people trying to play with ordinary mutable objects in transactions and getting strange results.
23:28ChouserScala doesn't have stong immutable vectors or hashes, does it?
23:29JamesIryVector, no. Set, hash map, etc yes
23:29rhickeybiting the bullet on immutability for all of the core data structures is one of the best things I did for Clojure. It's worked out better than I thought and I've gotten very little pushback from users, surprisingly.
23:29Chouserhm. I must have missed that.
23:30JamesIryhttp://www.scala-lang.org/docu/files/api/scala/collection/immutable$package.html
23:32rhickeywhat are the perf characteristics for the hash map O(log N) ?
23:32rhickeyimmutable != persistent
23:32JamesIryMost of their structures are persistent
23:33Chouserare those copy-on-write?
23:33JamesIryI think there's some ugliness in the way hashmap is done, though. I vaguely recall that that it was high on the list to get reimplemented.
23:33JamesIryChouser: I don't think they used copy on write
23:34rhickeypersistent just meaning old versions still available, or persistent meaning with perf characteristics intact? Amortized or not?
23:34rhickeyif you happen to know...
23:34JamesIryI don't know all the perf characteristics. Some are amortized using laziness and whatnot.
23:35JamesIryIt would be interesting to get you and them in a room. You guys are solving similar problems on the same platform.
23:35JamesIryRoom could be virtual, of course :-)
23:35rhickeyYes, I'd love to. I have to admit to having spent almost no time with Scala :(
23:36JamesIryWell...it's a bit like Java and ML had a love child.
23:36JamesIryVery different design philosophy from Clojure!
23:37rhickeyClojure owes some bits to ML
23:37rhickeyno type system though
23:37JamesIryYeah...I gathered the explicit ref types was a bit inspired by ML
23:37rhickeyexactly
23:38JamesIryOne of the things on my list is to investigate the Clojure/Scala boundary. Both will encode closures differently, for instance, but it seems like it might be easy enough to translate.
23:39rhickeyWell, Clojure is pretty transparent to Java - there are interfaces for everything, it uses the same stack and calling conventions, and there are no magic arguments, trampolines, CPS etc
23:40rhickeyno wrappers
23:40JamesIrySame with Scala - that's one area where both languages took the same philosophy: embrace the platform don't try to beat it into submission.
23:40rhickeyright
23:41JamesIryIn fact, with Scala if you stick to the Java-like subset you get pretty much the same bitecode as you'd get from Java. Things like closures just compile to instances of interfaces called FunctionN (where N is the number of arguments).
23:42JamesIrys/bitecode/bytecode
23:42JamesIrySigh...fat fingers tonight
23:42rhickeyClojure has a single interface, IFn, with overloaded invoke method for different arities
23:42JamesIryAh
23:43rhickeyallows you to pass a variadic function object to map et al
23:44JamesIryRight...good point. Scala's variadic functions are more like Java - the variadic argument becomes a single argument. The difference is Java uses and array, Scala uses an immutable list.
23:44JamesIryI suspect there are a fair number of differences like that. Many of them largely driven by the dynamic vs static nature of the languages.
23:45rhickeyyes
23:46rhickeyI expect between the two we cover a lot of what people with this, er, mindset might want
23:46JamesIryYup...the languages aren't going to attract the same crowd.
23:46ChouserI was attracted to both.
23:47Chouser...though I guess I'm pretty firmly here now. ;-)
23:47JamesIryWell, me too :)
23:47rhickeyI do think they both attract people interested in programming at a higher level than Java.
23:48rhickeyPeople will divide on static vs dynamic as always
23:48JamesIryOf course. Plus the standard Lispy macro stuff to which Scala has no answer at all right now.
23:49rhickey I see the next divide being about mutability, where Clojure and Scala may end up on the same side, the FP guys having gotten there first, but Java and the scripting langs having no good story
23:49JamesIryWell, I shouldn't say no answer, things like optional laziness and a reasonbly flexible syntax allow Scala to do SOME of the things I might want to whip up a macro for in a lisp. But only some.
23:50JamesIryrhickey: that is THE divide. the static vs dynamic flame wars are silly when compared to something as fundamental as that.
23:51rhickeyand yet, most people still don't even see that coming
23:52rhickeymulticore is going to smash into imperative programming like a train wreck
23:54Chouserevery method of scala's hashmap is synchronized -- that means locked, right?
23:54JamesIryThe hashmap impl is the one that sucks right now. I know its on their list
23:54Chousereven the get method, apparently because a get can trigger a mutation.
23:54Chouserthey should just use rhickey's.
23:54Chouser;-)
23:54JamesIry:)
23:55JamesIryDamn straight!
23:55rhickeyChouser: that's not inherently wrong, if they yield effective immutability
23:55ChouserI can't think why they shouldn't. Same license, I believe. rhickey's is Java, so they could just start using it.
23:55Chouserrhickey: I don't think it's incorrect, just not as efficient.
23:55JamesIryChouser: The api would be wrong, but the core algo would be fine
23:56JamesIryrhickey: it's not wrong, it's just silly. Plus, if I expect I'm using a normal immutable and persistent structure I'm not going to think about things like deadlock
23:57Chouserit looks like they keep a singly-linked list of changes to the structure, and occasionally re-collect into a new hash table. ...but I could be reading it wrong.
23:57rhickeythose are all possible implementations, delta chains etc
23:58rhickeywould need to be synchronized
23:58ChouserJamesIry: sure, but tidy little scala wrapper around PersistentHashMap would be easy.
23:58rhickeynot necessarily a deadlock risk, if there are no nested locks
23:58rhickeyI tried a bunch of things like that
23:59JamesIryrhickey: that's a good point. I suppose if some equals or hashmap method on a key was synchronized there could be risk of deadlock, but that's a pretty pathological case.