#clojure logs

2008-07-22

06:27meredyddHey - did anyone end up building (jmap)? I kinda got distracted over the weekend.
07:23meredyddhey, rhickey
07:23rhickeyhey
07:23meredyddHad a question about (jmap)
07:23rhickeyok
07:24meredyddWondering whether you'd consider a recursive version as well
07:24meredyddgive it a tree of Clojure collections, it gives you the same collection, but with every IPersistentMap replaced (or wrapped) with a Map
07:25meredyddIf you do it recursively, it solves the nested-Map problem I was talking about before the weekend
07:26meredyddSo, am wondering (a) Whether you think it's a good idea, and (b) if you did, what you thought of eager vs lazy translation
07:26rhickeyIf JavaMapOnPersistentMap implements both Map and IPersistentMap, is the only time you'd need this is if you were creating nested maps from literals?
07:27rhickeyi.e. if you always want maps that implement Map, won't you always use jmap to create them initially?
07:28meredyddAh - the problem I'm trying to solve is the one where you have lots of Clojure code on one side, which is slinging normal Clojure collections around
07:28meredyddand lots of Java code on the other side, which is slinging Java-idiomaic collections around
07:28meredyddand you don't really want to (or, if you're using libraries, physically can't) embed knowledge about the one into the other
07:29meredyddso you can't have the Java code slinging IPersistentMaps rather than java.util.Maps, and you can't have the Clojure code throwing (jmap) calls around everywhere
07:30meredyddso you have to do translation in the glue code.
07:30rhickeythen maybe it's more like jview - dynamically wrapping all values, but you'd want it on lists and vectors as well, no?
07:30meredyddyep
07:30meredyddwhich is the plan
07:30meredyddauto-wrapping Clojure lists, vectors, sets and maps in Java-idiomatic versions
07:31meredydd(although vectors and sets should be able to implement java.util.List/Set anyway, so it's more about making sure that any maps contained within them are wrapped too. Maybe even lists too, although I haven't looked closely)
07:31rhickeyat some point they'll implement List and Set, so it's only map values that won't be Maps
07:32meredyddIndeed. I'm prepping a patch to do List and Set implementations atm.
07:32rhickeyI wonder if you are solving a real and not a theoretical problem
07:32rhickeymost idiomatic Java code mutates collections
07:33meredyddHmm. I'm fairly sure I've seen collections with read-only semantics in the wild.
07:34meredydd(otherwise, nobody would ever use the Collections.xxx() immutable singletons and empties in anger)
07:37rhickeyyep, but note how they use a function (i.e. immutableMap), to get the view they want
07:37rhickeyunmodifiableMap
07:38meredyddOh, absolutely - I'm not trying to claim that immutable collections are the norm or the default in Java
07:38meredyddjust that being able to pass them into Java code is likely to be useful
07:39meredyddIn any case, I don't want to have a huge head-butting about it. I have a definite need for a subset of (jview) functionality in my current project, so I've written a quick and dirty version
07:39meredyddand I'll probably flesh it out to full functionality for my own use, sooner or later
07:40rhickeybut by the time you get to the use case of having idiomatic Java code that expects nested immutable collections, I think it's less real than theoretical
07:40meredydd'tis just a question of whether you'd be interested for mainline integration, and if so what sort of shape you'd prefer it to take.
07:40rhickeysimple jmap first
07:41meredyddokies.
07:41rhickey(jmap amp) returns an instance of something that implements Map and IPersistentMap
07:41meredyddokay
07:42rhickeyshould probably be written in Java
07:42meredyddYeah - the Clojure version is the basis of the quick and dirty hack :)
07:43rhickeyalso it should copy nothing, must implement emptySet, keySet and values with no copying
07:43meredyddUh-huh.
07:43rhickeythere may also be issues with hashCode semantics
07:44meredydd(Oh, sorry, of course - you never saw my java.util.Map implementation patch. I've already done that part.)
07:44meredyddrhickey: Actually, that's something I'd left blank, pending questions about equality semantics
07:44meredyddI'm *assuming* you'd want it to be equal() to the IPersistentMap it was created from
07:45meredydd(in which case, hashCode() isn't so much of a problem)
07:46rhickey"The hash code of a map is defined to be the sum of the hashCodes of each entry in the map's entrySet view."
07:46rhickeyugh
07:46meredyddOh, bugger.
07:48meredyddCould we not just change the algorithm for hashcode calculation in APersistentMap to match?
07:49meredyddoh, hold on. It's already an addition :)
07:49meredydd...ignore that line. Util.hashCombine is an addition. APersistentMap does a ^=
07:50meredyddDo you have great opposition to changing the APersistentMap calculation?
07:56rhickeybut it also dictates that it be the sum of Map.Entry hashes, which it dictates be a lame ^ of key and value hashes
08:00meredyddah.
08:02meredyddHmm...so, it's sacrifice equals()-equality with the source map, or equals()-equality with other java.util.Map implementations.
08:03meredyddCan I ask something unrelated for a moment, please?
08:05meredyddWhat would you say to allowing RT.print() to print Java collections in clojure reader syntax?
08:06meredydd(trying to figure out whether to do that or to stop using reader syntax as my wire encoding and go to something custom)
08:15rhickeymeredydd: at some point I want to move print out of RT and make it a proper multimethod. Printing for Java classes may move to JavaBeans XML serialization, so you can get back the same type
08:16meredyddOoh, clever.
08:17meredyddOff the top of my head, would a multimethod, dispatched on class, make it quite difficult to do, eg, a catch-all for "anything implementing Map"
08:17meredydd?
08:17rhickeyyes
08:18rhickeyof course you can get 'anything implementing map' runtime polymorphism in Java either
08:19rhickeystill thinking about how best to leverage interfaces in multimethods
08:19meredyddUhh...actually, that's one thing you can do. (In fact, pretty much the only thing you can do)
08:19meredyddpublic static void print(Map m)
08:19meredyddpublic static void print(Object o)
08:19rhickeythat's compile-time overloading, not polymorphism
08:20meredyddOh, point. In which case, yes.
08:20hoeckrhickey: gen-and-save-class doesn't create the package directory for the generated *.class property
08:21rhickeyhoeck: correct
08:21rhickeyenough people seem to be asking for it that I might change that, my only concern was creating directories on typos
08:25hoeckyou mean creating huge directories by accident?
08:27rhickeynot huge, just wrong. I guess my thought was, the namespaces, and thus the corresponding directories, would be created fairly rarely If I don't create them, then it can catch typos
08:29blackdogrhickey, did you get to record any video in Europe?
08:31rhickeyblackdog: I did get a screencast recording of the Lisp workshop, nothing from Dynamic Languages Symposium. I'm holding off on posting the Lisp Workshop as I'm giving a very similar talk to the Boston Lisp Group in September
08:32blackdogok, thx
08:33hoeckrhickey: okay, what about providing a 'create-dir' flag to genclass. I was fairly confused that it didn't wrote the dirs, and i thought is was my mistake ... until i read the java docs
08:34hoeckor maybe just mention it in the docs that the dir has to be created by hand
08:35rhickeyhoeck: hmm... (doc gen-and-save-class)
08:36rhickeyhoeck: I'm not opposed to the flag
09:20toyvoHi! Does anyone know where to look for documentation on the exact let form semantics? I'm thoroughly confused.
09:20rhickeytoyvo: http://clojure.org/special_forms
09:21toyvoBeen there. However let doesn't seem to nest with def as I expect.
09:22toyvo(do (def y) (let [y* y] (def y 1) y*))
09:22rhickeytoyvo: def is not Scheme define, def is always global definition
09:23toyvorihickey: I almost got that; however, I thought let is like Scheme let*
09:23rhickeyif you say (def y 1) at any level in namespace user, you are saying - I want user/y to be 1
09:23rhickeylet does bind sequentially
09:23toyvoYes, but why the expression above gives an error?
09:24toyvoIt says y is unbound (presumably the issue is in (let [y* _y_]
09:24toyvoI thought (let [y* y] ..) would mean let y* stand for y in what follows
09:24rhickey(def y) leaves y unbound, but your let tries to take its value in order to initialize y*
09:25toyvoExactly. But let shouldn't *take* values, or should it? Hm...
09:25rhickeylet is not an aliasing mechanism
09:25toyvoOk, is there an aliasing mechanism?
09:25rhickeylet binds names to the values of expressions
09:26toyvoEvaluating the expressions?
09:26toyvoOh, ok.
09:26rhickeyyes, it's not a lazy language
09:26toyvoRight :) My fault.
09:27toyvoSo, is there an aliasing mechanism?
09:27rhickeythere's no aliasing for vars at the moment, what are you trying to achieve?
09:27toyvoI'm trying to get at letrec, as a macro perhaps
09:28rhickeyah
09:28rhickeyletrec really needs language-level support
09:29toyvoWell a really heavy macro can do that, basically implementing a subset fo scheme, but that's going to be heaevy
09:29toyvoWasn't Scheme implemented on top of CL in the good old days...
09:30rhickeythe problem is, if you ar ecoming from Scheme, you might be used to mutually recursive letrec Schemes for state machines etc, but because Clojure has no TCO, that's not a good thing to emulate
09:30rhickeyletrec schemes
09:31rhickeyright no, only top-level defns can be mutually recursive. If you want them to be private implementation details, you can use defn-
09:31rhickeyright now
09:32toyvoYes, I know the no-TCO implications. Still, I'm kind of used to locally define functions inside other functions (it's the same in Scheme, Haskell, ML maybe)...
09:32toyvoAh.. Private functions? How private are those?
09:32rhickeyyou can totally define local functions, just not mutually recursive ones. just use (let [foo (fn []...)...
09:33toyvoYes, that's what I do when they do not recurse.
09:33toyvoLet me look up the docs on defn-
09:34toyvoAs a side note - is 'array?' predicate missing? 'vector?' is there
09:34rhickeyand they can self-recurse (let [foo (fn self [] ... (self)...
09:36rhickeyall of these blah? type predicates are kind of tedious. Maybe they made sense in Scheme where there are only 5 types, but once in a richer language with an open type set, at some point people have to deal with instance? (not directed at you, this comes up a lot)
09:37toyvoThat being said, (partial instace? clojure.lang.IPersistentList) is a bit verbose, is it not?
09:37Chouser#(instance? IPersistentList %)
09:37toyvothat's better :)
09:38Chouserof course that requires an (import), but you wanted to do that anyway. :-)
09:38toyvoBut still.. What I though of, is perhaps have a (type x) function, to returns keywords. That would help a lot. For example, to write polymorphics that dispatch on type.
09:39rhickeyarray? is an interesting case, as there is no common base type - > (.isArray (class x))
09:39rhickeytoyvo: why not (class x) ?
09:39toyvoYes, I thought about that. How about representing their 'types' with vectors of subtype? Like [:java.lang.String]
09:40rhickeywhat' wrong with classes?
09:40rhickeywhat's
09:41toyvorhickey: hmm.. like you say - arrays; also, what are semantically clojure lists can be represented by different classes
09:41Chouserthat one comes up a lot too.
09:41rhickeyStill, there's no reason to parallel the type system with keywords IMO.
09:42rhickeyinstance? can check for interfaces
09:42Chousertoyvo: "semantically clojure lists" means things that (seq) works on?
09:43toyvoChouser: no. Sometimes you want to differentiate between lists and vectors. That's the case I have in mind.
09:44toyvoOkay then - if the language stick with (instance?) checks, for consistency - why don't drop vector? predicate :)
09:44Chouserhm. seq? might do what you want, I guess depending on what you mean by "list"
09:44toyvolist as in IPersistentList
09:44rhickeySee - once you define list then you have to keep explaining what it means
09:44rhickeyseq?
09:44toyvoAh
09:45rhickeyall the predicates
09:45rhickeyThere are some useful marker interfaces too, like Sequential
09:45toyvoAh (seq? [1 2 3]) is false.. Nice. i didn't know that.
09:46rhickeyuser=> (seq? ())
09:46rhickeyfalse
09:46toyvoWhy is that?
09:46rhickeysee?
09:46rhickeybecause an empty list is not a seq
09:46toyvoOh my
09:46rhickeya seq always has a first
09:47rhickeyotherwise it would be nil
09:47rhickeymost lists are their own seqs, but not ()
09:47toyvoI'm used to this definition: List x = Nil | Cons x (List x)
09:48toyvoSo seq? is actually testing for Cons part
09:48rhickeynil can represent any type, so the type constructor analogy breaks rapidly
09:49rhickeyseq? tests for ISeq
09:49toyvoWonderful Java platform :)
09:49toyvoOK, I'll check that.
09:50toyvoMaybe I'll have to write about this on the Wiki, in the "for Scheme programmers" section
09:51toyvoCan I build the Javadocs for Clojure? Or are they online?
09:51toyvoTo look up ISeq and all the rest/
09:51rhickeyThis is Clojure design, and it is nice, but one can't take the presumptions of a world with one (concrete!) list type and apply them to one with a rich set of overlapping abstractions
09:51rhickeyChouser did a neat class diagram
09:53rhickeyhttp://groups.google.com/group/clojure/msg/ef51d43ea0898c81
09:53ChouserI need to post a new one, that one's a bit out of date.
09:53toyvoThanks
09:53toyvoBut still - can the javadocs be built?
09:54rhickeytoyvo: I think you can always get a mechanical JavaDoc, but I haven't manually written any yet - sorry
09:54toyvoNo problem... Hopefully it will come later. You are doing a great job anyway.
09:56toyvoAnother q: Is there a structure preserving map? like (fmap (partial + 1) [1 2 3]) -> [2 3 4]
09:56meredyddrhickey: Okay, I think I have a patch with List and Set support
09:57meredyddcovering APersistentVector, ASeq, and APersistentSet
09:57meredyddNeed to test it properly, though
10:06toyvoI modified the ANT buildfile to have a new target, docs, which builds the javadocs. Should I mail the tiny patch?
10:06rhickeytoyvo: (into (empty x) (map f x))
10:07toyvorhickey: yes, but that has not polimorphism. I want fmap to preserve structure (list to list, vector to vector, set to set)
10:08toyvoYou can also view the (mechanical) javadocs here http://clojure.fajno.net/
10:08rhickeyempty is polymorphic
10:08toyvoAh
10:08toyvoNie
10:08toyvoNice
10:09meredyddrhickey: I think I have a patch for List and Set support. Also (dependently), I've modified RT.print() to work with all Lists, Sets and Maps with normal reader syntax.
10:09rhickeymeredydd: cool, can you post (List/Set patch) to the group? print I'd like to consider separately
10:10rhickeytoyvo: would it be possible to limit to just clojure.lang, asm is an implementation detail
10:11toyvoI will try! It gave me an error before, but I'll try.
10:16meredyddmeredydd: Okay. There's a slight overlap, in that both modify RT (I've made subvec() return APersistentVector, so as to make subList() work), but it's trivial
10:16toyvorhickey: limited to clojure.lang, uploading.
11:00meredyddrhickey: Posted. Feedback welcome.
11:49rhickeymeredydd: still looking at it. I kind of hate the List interface for non-indexed collections (not your fault, it's just such a bad fit)
11:50rhickeypersonally, I wouldn't support it for other than vectors
12:03rhickeymeredydd: I don't think all Lists should print like [..], only RandomAccess derivees
12:42rhickeyi've made vectors implement java.util.List and sets implement java.util.Set
12:48lisppaste8drewr pasted "Function dispatch on string" at http://paste.lisp.org/display/64047
12:49drewrI need (symbol ~cmd) to return the function pointed to by that name. What am I overthinking here?
12:50Chousercmd is a string?
12:50drewrYes.
12:52drewr(dispatch-cmd "foo" 1 2 3) should expand to (apply foo '(1 2 3)). At least I think that's the way I want to do it.
12:52ChouserI think to go from string to function you'll need eval.
12:52Chouserand if not, rhickey will just in here and shout at me in a moment.
12:53Chouser(defmacro dispatch-cmd [cmd & args] `((eval (symbol ~cmd)) ~@args))
12:54Chouserthat's dropping the args in place rather than going through apply.
12:56drewrYeah, that works for me.
12:56Chousergah, no
12:56Chouser(defmacro dispatch-cmd [cmd & args] `(~(symbol cmd) ~@args))
12:56Chouserthat's what you (and I!) were over-thinking.
12:57drewrAhhh. Yes.
13:07meredyddrhickey: Hmm. That's two halves of the same thing.
13:07meredyddrhickey: There's a definite mismatch with sequences, which are most definitely ordered but a pain to index
13:08meredyddrhickey: OTOH, Java treats LinkedList as a List, so I reckoned it should be your call.
13:09meredyddrhickey: I'm also happy with only RandomAccess being printed with [...] - but can we have (...) for everything else, in that case?
13:09meredydd(in fact, (...) for all Iterables would be swell)
13:15lisppaste8drewr pasted "Exception not caught" at http://paste.lisp.org/display/64050
13:16drewrI don't understand this. (bar) is throwing the same exception I caught just before it. Am I missing a paren somewhere?
13:19kotarakI suppose this exception is thrown during compilation because bar is not defined. But your code only catches exceptions at runtime.
13:20drewrkotarak: Yes, that's probably correct.
13:21meredydddrewr: (try (eval '(bar)) (catch Exception e "darn!"))
13:22meredyddDelay compilation till runtime, and run-time (try) will catch it
13:24drewrmeredydd: Good call. Thanks.
13:38rhickeymeredydd: as I said earlier, I might want to do a printed version of Java data types that reads as the original type, so unifying with the Clojure types would not be something I'd want to promise long-term (request for a flag coming, I'm sure :)
13:39meredyddheheh
13:39meredyddActually, for once, no (at least not from me)
13:39meredyddBut is that a "go" for [...] for vectors?
13:40rhickeynot if I later want ArrayList's print representation to read an ArrayList
13:40meredyddOkay, so that's a no then
13:40meredydd(or "not in the immediate future")
13:42rhickeymeredydd: wouldn't you want read/print for Java types?
14:43stacktraceris there a bug tracker for clojure?
14:43rhickeydo you have a bug?
14:44stacktraceryes, unless I'm misunderstanding something
14:44rhickeyyou can paste it
14:44stacktracerNumbers.java, line 1311
14:44stacktracersure
14:45stacktracerin Numbers.double_array(sizeOrSeq), the value assigned to ret[i] is truncated to an int
14:46stacktracer(let [a (double-array '(1.2 2.3))] (aget a 1))
14:46stacktracergives:
14:46stacktracer2.0
14:47stacktracer(I expected it to give 2.3)
14:50stacktracersimilar thing with float_array at Numbers.java:1280
14:51rhickeyall fixed - thanks for the report
14:52stacktracerawesome -- thanks
14:52kotarakbugtracker? what for? ;)
14:56rhickeykotarak: exactly
14:56rhickeyoutstanding bugs are just a source of stress
14:56kotarakno pet bugs, my motto
16:29Chouserrhickey: are you at all sympathetic to reader syntax for apply? Something like (f @args) instead of (apply f args)?
16:30Chouserhm, not @ of course. or * (like python).
16:33rhickeyChouser: probably not - the best argument for reader syntax is to remove a set of parens, which this doesn't
16:33Chouserok
16:37hoeckrhickey: what about a reader macro like & but not generating a list but instead a hashmap?
16:37mebaran151what's the best way to do io in clojure
16:37mebaran151it seems rather unfortunate to have to call into nasty java to do reads
16:38rhickeyhoeck: looking for keyword args are you?
16:39hoeckrhickey: yeah, kind of
16:40cemerickoh noes, not more standard read macros! :-)
16:40rhickeyI keep thinking this should just be a destructuring variant, but haven't thought much more than that about it
16:40hoeckjust a thought, i'm doing pretty well with hashmaps
16:40cemerickrhickey: You mentioned you were taking the reflection out of proxy at some point; has that happened, or not yet? (I've been concentrating elsewhere of late.)
16:40rhickeythere aren't going to be any infix ops, read-macro or otherwise, this is not Arc
16:41hoecki often come across (defn fun [arg options] where options is a hashmap and then somewhere in the function body: (merge options *default-options*)
16:42rhickeyhoeck: it would be easy to write a defnk macro that did the boilerplate for you
16:43rhickeycemerick: I haven't figured out if it is possible yet
16:47hoeckrhickey: what do you think about keyword args, good/bad/ugly??
16:48rhickeyhoeck: I like them, but they are not primitive, so not in fn
16:51rhickeyhoeck: this is an old one I whipped up, even easier now: http://groups.google.com/group/clojure/msg/51bb53ca077154f8
16:52cemerickrhickey: ok, thanks, just checking. Would you be open to a patch that added a protected function makeNew to PersistentStructMap that passed on all of the arguments needed by PersistentStructMap's constructor, and routed all PersistentStructMap constructor calls through that makeNew function? Something like that will be necessary in order to implement the structmap/javabean notion we've talked about a couple of times.
16:54rhickeycemerick: refresh my memory - why is this needed?
16:54hoeckrhickey: i'm afraid of using keywords cause they are not included in `the standard', it feels like bad style writing my own defn macros
16:55hoeckkeywords -> keyword args
16:55rhickeyhoeck: then think about a destructuring variant to support them
16:58cemerickrhickey: I'd like to be able to define a struct that subclasses PersistentStructMap, and whose fixed keys' values are returned by suitably (and automatically) named methods on that subclass. The patch I just suggested is necessary to allow the subclass to easily return an instance of itself as the result of assoc, etc (rather than it returning an instance of PersistentStructMap).
16:58cemerickThat makes for a data structure impl that can cross the clojure/java divide, and be used in optimally "native" ways on both sides.
17:03rhickeyare the fixed fields stored as Java fields or still in an array?
17:03cemerickThe fixed fields are stored in PersistentStructMap's vals.
17:05rhickeycemerick: I'm hesitant only because I used to have a lot of that polymorphic construction in the library and it becamse very fragile - and that was with me controlling both base and derivee. You've considered the containment option as well?
17:10cemerickrhickey: Understood. Yes, composition is my fallback. The only downside of that is additional complexity in the macro and generated classes involved...but, a downside I'd obviously like to avoid. :-)
17:10rhickeywould Java clients access extended keys?
17:11rhickeywould there be an interface corresponding to the fixed keys?
17:12cemerickrhickey: (1) sure, via valAt (or, perhaps via a more idiomatic java method name)
17:12cemerickrhickey: (2) yes, each fixed key would get a java method generated for it that fetched the current value of the corresponding key
17:12cemerick(2) is what really makes it all worthwhile
17:13rhickeycemerick: no, I meant an Interface corresponding to the set of fields
17:14cemerickrhickey: Ah -- not by default -- it'd be a concrete bean. I would provide an option to specify an interface that the keys map correspond to, though.
17:17cemerickrhickey: If you'd prefer, I can post a composed implementation, and we can consider a patch to PSM later. No need to force these sorts of things on the spot.
17:21rhickeycemerick: the PSM patch would be easy and harmless, it's the evolution/maintenance problem, for instance at some point I'd like to make most data structures Serializable. Do you add any fields in your derivee?
17:23cemerickrhickey: No -- just what's necessary to make the fixed keys' values available via corresponding methods. All of the model absolutely stays within clojure.
17:27rhickeycemerick: alright, why don't you post the patch to the group - did you send me a CA yet? (haven't checked the box yet today)
17:28cemerickrhickey: OK, will do. No, I haven't sent in a CA. I'll ship one to you tomorrow.
17:28rhickeycemerick: can you email me a scan while it's on the way?
17:29cemerickrhickey: sure, np
17:29cemerickrhickey: thanks, as usual :-)
18:15meredyddrhickey: Say again? What did you mean by "Wouldn't you want read/print for Java types"?
19:07rhickeymeredydd: wouldn't you want the printed version of say, ArrayList, to read as an ArrayList (rather than a vector)?
20:09meredyddrhickey: Above all, I'd like it to read as a List.
20:09meredyddrhickey: I'd be happy with ArrayList if it round-tripped well
20:09rhickeyList is an interface, read returns a concrete data structure
20:10rhickey[1 2 3] is going to be a Clojure vector, not an ArrayList
20:10meredyddIndeed; what I'm saying is that I don't care *what* it is, as long as it implements List
20:10rhickeyso printing ArrayLists as [1 2 3] won't round-tri[p
20:10meredydd(although I can see that not exactly being an, ahem, general solution :P)
20:11meredyddMy personal position was that, assuming as I was that there were no extra primitives going to be added to the reader,
20:12meredyddthat I would prefer an ArrayList to come back as at least *something* implementing List
20:12rhickeyI'm sure the reader will be extended to more Java types
20:12meredyddrather than a reader failure (which is what would have happened otherwise)
20:12meredyddin which case, the assumption upon which I based that feature request was flawed.
20:12rhickeyas I said, probably based on some generic mechanism like JavaBean serialization
20:13meredyddThe underlying problem is "I have an object, I need to get it from here to there"
20:13meredyddJavaBean serialisation would do the trick, verbosity notwithstanding.
20:15meredyddOoh, by the way, while we're talking about the reader - there's what looks like a subtle round-tripping bug in the metadata stuff
20:16meredyddif you put a map into an obj's :tag
20:16meredyddthen write it out with metadata output turned on, then read it back in, you get that map as the whole metadata rather then the tag
20:17meredydd(why anyone would do this, I have no idea, but it struck me looking through that code)
20:17rhickeycould you paste an example?
20:19meredydd(def x (with-meta 'quack {:tag {:x 15}}))
20:19meredydd(binding [*print-meta* true] (prn x))
20:19meredydd--> #^{:x 15} quack
20:20rhickeyah
20:20meredyddIf I can find a more obscure or trivial bug, I shall be sure to let you know ;)
20:21meredyddin RT.java:
20:21meredyddif(meta.count() == 1 && meta.containsKey(TAG_KEY))
20:21meredyddadding an instanceof check should do it
20:36rhickeywow, XMLEncoder version of ArrayList is verbose!