#clojure log - Jun 16 2008

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

8:18 asbjxrn: Got a macro question: I've got a map of symbols/values and would like to turn it into a binding of those symbols/values. (and have a body being executed within the binding.)

8:19 I haven't managed to come up with a suitable combination of quotes, tildes and @...

8:19 (actually, when I think about it, it doesn't have to be a macro....)

8:20 rhickey_: right, see Var.pushThreadBindings/popThreadBidings as used by binding and with-local-vars

8:21 maybe with-local-vars is what you need

8:23 asbjxrn: What I want is variables that look "normal" to a user, but which differs between threads/agents.

8:24 rhickey_: that's what vars are

8:24 asbjxrn: Right,

8:25 Hmm. So maybe I don't have to do anything special at all...

8:27 meredydd: asbjxrn: I might be missing something here...but why don't you just wrap (let)?

8:27 asbjxrn: No, I think I might have to. What I have is swing frames/panels and I want each to have a separate set of variables local to each frame.

8:28 rhickey_: asbjxrn: how would you name them?

8:29 asbjxrn: I have a "env" map that is in a closure around the Jpanel. In that env map I have a :vars value which I thought to have as a map of symbols.

8:30 rhickey_: but if you are going to write code using those symbols, they're not runtime names, so why not pick names for def-ed vars?

8:30 asbjxrn: Then in the "paint" function of the panel, I was going to do a (foreach symbol in (env :vars) do binding symbol value.....) then call the render.

8:31 The thing is I let the user define what happens in the render function and I'd like the user to create/use variables in there..

8:31 Maybe an example is easier.... just a moment....

8:31 (This is kinda processing-inspired)

8:36 lisppaste8: asbjxrn pasted "processing lite" at http://paste.lisp.org/display/62316

8:37 asbjxrn: There are som examples at the end there.

8:40 rhickey_: ok, so where are you stuck?

8:41 asbjxrn: sorry, phone...

8:44 Ok, so far I have some variables already, if you see in the make-panel function I set up mouse position etc. before I do the render.

8:46 The next trick is to let the user add variables himself. To do that the binding of those variables have to be dynamic somehow. If I could just loop through the symbols in (@env :vars) I could just define a function that adds it into that map.

8:46 I'm sorry, it's quite a bit of code, I don't really have a small test case for this...

8:47 rhickey_: do you know CL?

8:47 asbjxrn: Somewhat.

8:47 rhickey_: would symbol-macrolet let you do what you want?

8:47 asbjxrn: That one I have never used, let me read a bit...

8:51 Hmm, I don't know. I think the binding part that I already use (see the paint function in make-panel) works well, what I'm struggling with is to map that over all the entries in the map, not just the predefined ones.

8:53 rhickey_: right, but for Clojure to resolve the unadorned symbols as references to particular vars, they need to be def-ed,

8:53 but you are writing a DSL via macros, where you want to extend the namespace and resolution rules

8:54 asbjxrn: Yes, so I would need a function for the user to setup the vars, that function could def it, bind it for immediate use and add it to the map.

8:54 rhickey_: maybe, but the def has to be visible when Clojure compiles the body

8:55 what would typically happen if you had symbol-macrolet would be the macro would have x turn into (get env 'x)

8:55 asbjxrn: Yes, I had this working with a whole evaluator and stuff. Was a lot of work when I had to start doing my own doseqs, ifs etc. I kinda ripped that out and the only missing thing now is the vars....

8:56 Ok.

8:58 But I guess clojure doesn't have symbol-macrolet?

8:58 rhickey_: right, you don't need a whole evaluator, just a runtime name environment

8:58 no, no symbol-macrolet yet :(

8:58 asbjxrn: The "yet" is a good sign :)

8:59 rhickey_: yes, of all the tricky CL macro stuff, symbol-macrolet is the one I want most

9:01 asbjxrn: I guess I could just tell the user ( me :) that I have to use normal variables.

9:01 rhickey_: for now, or try with-local-vars

9:03 asbjxrn: They have to be persistent between renders.

9:03 Not sure how swing threads work and how that would work with with-local-vars?

9:07 rhickey_: so, with-local-vars wouldn't help (don't persist), but the thing to take away from that is that vars are ordinary objects, you can create and store in your own map. Then maybe your macro has to look for 'your' vars and emit binding code

9:08 that binding code would use Var.push/popTreadBindings, not 'binding'

9:09 asbjxrn: Ah, now I get your first reply, I could make something using the Var.push/pop... Sorry for being slowl

9:10 Feels a bit dirty, like using non-exported functions in CL.

9:10 rhickey_: np, the mechanism behind vars isn't really documented, but 'binding' and 'with-local-vars' provide examples

9:12 well, the problem is properly exporting them means pairing push and pop, since otherwise it's broken, and that means a macro, and those 2 are those macros. I guess I could provide push-thread-bindings but that doesn't add too much value

9:12 other than to document it is ok

9:13 asbjxrn: Don't worry for my sake.

9:14 la_mer: rhickey_: Browsing around the google groups, I saw you mention a couple times that you were planning some higher-level content talking about data design in clojure (i.e. fully utilizing the freedom afforded by clojure's dispatch mechanisms, etc). Is that stuff out there somewhere, or is it still on the drawing board?

9:15 rhickey_: la_mer: still to come. I think I might get to that material first when I resume my lunch talks with my think-tank group as we get past the basics

9:18 la_mer: rhickey_: is there some analogous content you know of off the top of your head that uses other languages (maybe scheme)? Clojure obviously has some unique features, but I'm thinking that maybe there's some "practical" (i.e. non-research-oriented) material that touches on some similar concepts.

9:24 rhickey_: not exactly sure which aspects, but as a general thesis, this is a good paper: http://web.mac.com/ben_moseley/frp/paper-v1_01.pdf

9:25 note that Clojure doesn't adopt the in-memory relational part (but does offer some facilities), but I think is on the right track in providing guidance in how to think about these things

9:27 but in terms of how to do the whole thing, STM + Agents + persistent data structures, I don't think there is anything because I think Clojure is the first language to propose this as the standard mechanism

9:27 la_mer: rhickey_: That looks very promising, thanks. A good springboard into related material via citeseer, etc.

10:46 yrb: Does seperating the gui out into an agent to try and hide the mutable state sound like a good idea?

10:48 tomhickey: The clojure site is looking good :)

10:48 tomhickey: yrb: thanks

10:56 asbjxrn: yrb, I thought so, and Rick used it in his ants demo, didn'so it can't be all bad?

10:57 didn'so -> didn't he, so

11:08 yrb: Hrmmm, Well he more used an agent to manage the render. The gui didn't really have much state as such

11:10 asbjxrn: Ah, you want to hide the state of the gui in the agent. That is what I kinda (try to) do, but I just have a toy thingy.

11:12 yrb: I suppose a immutable representation of the gui behind a ref would be the best

11:12 and have agents render from that

11:13 asbjxrn: What I do is to put a panel in a closure which contains various state, and the panel itself, and set the angent to be a ref to that closure.

11:15 So the only way to get to the state or even the panel itself is through the agent, which is a ref.

11:15 Chouser_: asbjxrn: I'm just barely following this, but if you'll indulge me ... how does your closure change its state? or does it?

11:17 asbjxrn: Well, I have very little state to be honest. It is changed through actions(?) sent to the agents and could also be changed in the render function when the panel do a repaint.

11:17 yrb: how do you do your callbacks?

11:19 asbjxrn: Well, this is where the toy example comes in I guess. I just have a panel that I draw in. It is a proxy, and I have defined mouselisteners etc.

11:19 Chouser_: asbjxrn: I'm sorry, what I meant was that when I have a closure that has state, its usually by using (let ...), but then I can't change those values.

11:20 asbjxrn: do you use let and some refs? can't be thread-binding since different threads could handle that agent, right?

11:20 asbjxrn: Ah, the closure is a ref of a map.

11:20 Chouser_: ah, ok.

11:22 lisppaste8: asbjxrn annotated #62316 with "refs, agents and gui" at http://paste.lisp.org/display/62316#1

11:22 asbjxrn: I pasted it just now. http://paste.lisp.org/display/62316, if you can wait a little bit I'll

11:22 Oops.

11:23 Very raw, I'm in the process of at least adding some minor comments.

11:23 Chouser_: It's fascinating that when someone says "state" it either has to never change or be using one of a very short list of mechanisms for change.

11:24 asbjxrn: I don't mean that at all.

11:25 Chouser_: is "defn-" defined somewhere?

11:25 asbjxrn: The comments at the bottom shows how it is to be used, the draw/once/on-click sends actions(?) to the agent to change how the panel is updated.

11:25 I think so. It a defn that is not exported(?) from the namespace

11:26 Chouser_: oh! cool.

11:26 indeed. boot.clj

11:26 Maybe I should be reading the svn diffs -- apparently reading boot.clj once weeks ago isn't enough. :-)

11:28 asbjxrn: I wish I had the time you apparently have :)

11:28 I haven't even looked at the parallell and native-number stuff.

11:29 Chouser_: oh. neither have I.

11:29 asbjxrn: that's a fascinating thing you've built there.

11:30 yrb: asbjxrn: Cool, thanks for that :)

11:31 asbjxrn: It's not that fantastic. It's actually just a result of me not being able to get processing to work with clojure, so I started writing something like it instead. It's just a learning project.

11:33 The state in this example is mostly the list of commands to be executed in the render function. And the mouseclick/move stuff.

11:36 Chouser_: so does anyone here understand how "commute allows for more concurrency" than alter or ref-set?

11:40 it seems to me that either way, if one transaction conflicts with another, the loser has to go back to the beginning to get fresh state to do its calculations.

11:44 asbjxrn: I think it means that it won't do that.

11:44 Thus: the fun should be commutative.

11:45 Hmm. No. doesn't make sense that way either.

11:49 It would make sense that way if commute was atomic, so you could be sure that nothing gets inbetween the call to fun and the assignment.

11:49 I think.

11:54 From the google group Rick says: "It also supports explicit

11:54 commute, further reducing retries for commutative writes"

11:55 blackdog: noobie question, in (def *accountInfo*) are the stars just convention for a global variable?

11:55 asbjxrn: Which I take to mean that the transaction won't be restarted. It might be a good question for the group, though.

11:55 blackdog: or is it more significant

11:56 asbjxrn: It's a common lisp convention. I haven't seen anyone use it in clojure. Where did you see it?

11:57 blackdog: can't remember now, probably from rich's code

11:57 i've never looked at CL so it can't be from there :)

11:57 Chouser_: yeah, it's convention for globals. Clojure provides *warn-on-reflection*, *command-line-args* and maybe others

11:58 but the compiler doesn't do anything differently just because of the *

11:58 blackdog: ok, thanks all

11:58 ok

11:58 jteo: always thought it was a CL convention

12:03 Chouser_: asbjxrn: I think you're right. at least as long as the fun passed to commute only looks at the ref passed to it, there's no reason the whole transaction would have to be restarted.

12:08 rsynnott: jteo: I suspect it has been borrowed

12:08 (it's certainly a CL convention)

12:08 quite a good one, really

13:24 meredydd: Is there an idiomatic way of creating modules with a particular "public" API?

13:26 So, I'm writing a chunk of my application in a namespace, and I really only want the rest of the world to interact by calling a few functions.

13:27 Chouser_: yes, you can mark items in the namespace as private

13:27 specifically, you add a :private key to their meta-data with a value of true

13:27 meredydd: Ick. And I have to do that for every fn?

13:28 Chouser_: yes. There's a variant of defn named defn- that does it for you

13:28 meredydd: Is there a shortcut?

13:28 Chouser_: ...just learned about that today.

13:28 meredydd: Tadaaa. Thank-you muchly :)

13:28 Chouser_: :-)

13:31 Huh. That's been there since March 10th.

14:36 drewr: How can I convert a lazy seq of seqs into one lazy seq of the elements of each seq?

14:36 Chouser_: concat

14:37 Lau_of_DK: Chouser, isnt he asking about flatning it ?

14:37 drewr: I guess I can chain CONCATs together.

14:37 Lau_of_DK: Yes.

14:37 Lau_of_DK: drewr, so you need lazy-flat ?

14:37 drewr: Actually, chaining won't work because it's all one seq.

14:38 Chouser_: (apply concat [[1 2 3] [4 5 6]])

14:38 drewr: Ah, I think that'll work.

14:39 Chouser_: And it's fully lazy: (take 5 (apply concat [[1 2 3] (iterate inc 10)])) => (1 2 3 10 11)

14:39 drewr: That's awesome.

14:39 * drewr is still trying to think combinatorically

14:39 Chouser_: :-)

14:44 drewr: Now I have a lazy stream of messages from our database of *millions* of rows.

14:44 Chouser_: very nice.

14:44 drewr: I run a LIMIT query getting a batch at a time.

14:44 And splice them all together in a lazy seq.

14:45 Chouser_: oh, VERY nice.

14:45 drewr: This is turning out to be a decent SQL lib.

14:45 Lau_of_DK: Chouser, did you decide wether or not (def) was threadsafe?

14:46 drewr: Lau_of_DK: Use VAR-SET in a BINDING.

14:46 Lau_of_DK: For concurrency I think I'll use Refs, but I was just asking out of interest because Chouser investigated the inner workings of (def) quite heavily last time we spoke :)

14:47 drewr: Ah.

14:47 Lau_of_DK: (yes, I know the poor man needs a real hobby)

14:47 Chouser_: Lau_of_DK: rhickey says yes: http://clojure-log.n01se.net/date/2008-06-15.html

14:48 Lau_of_DK: k, thanks

14:48 Chouser_: drewr: how hard would it be to have the use of the last (minus n) item of batch 1 cause the fetching (in the background) from the db of batch 2?

14:49 or would that even be desirable?

14:49 drewr: Chouser_: Interesting idea. I'm not sure if it would be necessary or not.

14:50 In theory your batches should be small enough to be really fast queries, but big enough to chew on without hitting the database every 500ms.

14:50 Chouser_: yeah. I was just thinking the an attempt to use the first item would block waiting for the db server to respond, right? and that maybe that could be avoided.

14:51 anyway, what you've got is very cool.

14:51 drewr: Yes, there would be some blocking depending on how fast the query returns.

14:51 Chouser_: mind sharing the code so I can pass it along to some friends later this week?

14:51 drewr: Yeah, I'll share it once I clean it up.

14:53 Chouser_: great, thanks.

14:54 drewr: I bet I could queue up a batch in a Ref, and then in a transaction grab the batch, empty the Ref, and be populating it with the next batch in another thread.

14:58 la_mer: Looks like clojure doesn't work out of the box on ikvm...

14:59 Chouser_: hm... interesting idea.

14:59 how does it break?

15:00 la_mer: The compiler pukes looking for a matching method for append on a printwriter.

15:00 (this is while compiling boot.clj)

15:03 jamii_: Is there no prepend function for vectors?

15:04 Chouser_: jamii_: If you want fast prepend, lists might work better for you.

15:05 jamii_: I need fast prepend, append and indexing. I guess I'll have to go with a pair of vectors.

15:12 la_mer: looks like an ikvm bug -- it seems to be providing doubles for all possible methods (maybe?), so clojure can't resolve a match

15:38 Not sure what's going on here...this throws a ClassCastException: (map #(%) [1 2])

15:43 Chouser_: it's trying to run 1 and then 2

15:46 did you mean for the function to a sort of no-op? you might try (map identity [1 2])

15:48 la_mer: I'm just messing around with the shorthand function syntax....isn't #(%) the same as (fn f [v] v)?

15:49 Chouser_: no, it's the same as (fn [v] (v))

15:51 la_mer: ah, didn't read the docs closely enough

15:51 Chouser_: yeah, that's a subtle bit that several of us have tripped on.

15:52 la_mer: #(...) => (fn [args] ...) is how I read it

15:52 Chouser_: makes sense, though, or most of the time you'd end up writing #((foo %1 %2)) or something

15:53 la_mer: Sure.

15:53 It's a little too bad that % was chosen instead of _, but that's bikeshed territory, I suppose.

16:04 Clojure *does* seem to work via ikvm / ikvmc, but you need to use v0.36 of ikvm -- v0.34 does not work

16:04 Chouser_: really!? that's pretty cool.

16:05 la_mer: Well, I get a Repl prompt :-)

16:05 Is there an automated test suite somewhere. I see a Test.clj file, but there's nothing there.

16:05 Chouser_: boot.clj. :-)

16:05 la_mer: Uh-huh. :-D

16:06 That's a *little* scary.

16:07 Chouser_: I think someone was working on a test suite.

16:08 http://clojure-log.n01se.net/date/2008-05-20.html

16:14 Lau_of_DK: Anybody worked out how to execute a .clj that accepts args?

16:14 blackdog: i have script somewhere

16:14 Chouser_: java -cp clojure.jar clojure.lang.Repl a.clj -- some args

16:15 Lau_of_DK: ok - and then I access these as standard java-args ?

16:15 la_mer: Is Rich's ant colony code up somewhere?

16:15 Lau_of_DK: la_mer, its in the google groups files

16:15 Chouser_: Lau_of_DK: there's a global *command-line-args*

16:15 la_mer: Lau_of_DK: thanks

16:16 Lau_of_DK: Chouser, sweet

16:20 la_mer: Aside from ikvm's lack of support for awt, ants.clj seems to work in .NET

16:22 Lau_of_DK: This might be a silly question, but whats the use of ikvm? Why put Java in .Net ?

16:22 Chouser_: so you can run Clojure on .Net!

16:22 Lau_of_DK: And use .Net libs instead of Javas?

16:23 la_mer: We use it to offer .NET versions of our libraries.

16:23 Lau_of_DK: k

16:24 la_mer: You can use .NET libs from a Java app cross-compiled using ikvm, although you need to generate stubs from the relevant .NET assemblies so javac can have something to work with.

16:24 Using .NET assemblies should be a *lot* easier with clojure, since compilation happens at runtime.

16:25 Many of our larger customers deploy to .NET exclusively, so having some confidence that clojure is ikvm-friendly is pretty important.

16:25 Lau_of_DK: Sure - And .Net is home to me, so in that regard im positive, but Im sure Rich has a reason to sit Clojure on the JVM instead of .Net ?

16:26 blackdog: i think he started out by being able to compile to both, but went for java in the end

16:26 la_mer: I think he's provided his reasoning on that choice before, elsewhere.

16:26 blackdog: yeah, that's right.

16:26 Many people seem to consider the jvm as being a friendlier host for "alternative" languages. I don't know the details.

16:26 Lau_of_DK: la_mer, how difficult is it to run clojre on .Net instead of Java?

16:27 blackdog: la_mer, if you read the blog of charles nutter, he has lot's of opinions on that

16:27 la_mer: Lau_of_DK: Just grab ikvm 0.36, and compile clojure.jar down to an exe (or DLL, if you were to embed it into another app).

16:28 Lau_of_DK: and then just run clojure.jar.exe myclj.clj ?

16:28 la_mer: Lau_of_DK: I don't have my command line open anymore, but it's as simple as "ikvmc -target:exe -out:clojure.exe -main:clojure.lang.Repl clojure.jar"

16:28 Lau_of_DK: Thats too easy - This is some serious cross-platforming

16:28 la_mer: blackdog: Yeah, I know...I only follow him occasionally, mostly because JRuby is uninteresting to me. :-)

16:29 Lau_of_DK: Yes, essentially -- although you'd want to make clojure.lang.Script your main method in that case

16:29 and, FWIW, I've not messed around with touching .NET bits from clojure, so there may be hidden dragons there.

16:31 Lau_of_DK: I cant tell if .Net is "better" than Java, but I think if nothing else, the libraries are insanely easy to dive into

16:41 http://java.sun.com/javase/6/docs/api/javax/swing/ImageIcon.html#ImageIcon()

16:41 Guys, shouldnt this work

16:41 (import '(javax.swing.ImageIcon))

16:42 (let [image-holder (ImageIcon.)]) ?

16:42 blackdog: leave a space afer swing

16:42 Lau_of_DK: shoot me

16:42 :)

16:49 You guys had any problems with "No matching cstor" ?

16:50 blackdog: make sure you have the right type passed to the function

16:50 can't find the constructor for the type you've given it

16:51 Lau_of_DK: So you mean something #^String ?

16:51 ImageIcon(String filename)

16:51 Creates an ImageIcon from the specified file.

16:52 blackdog: you don't need to give it a type hint i don't think

16:52 Lau_of_DK: How would you initialize that?

16:52 blackdog: oh

16:52 so you eant to do

16:52 (ImageIcon. "path to my file")

16:52 Lau_of_DK: And thats what I have now

16:52 blackdog: sure it's a filename and not a file?

16:52 Lau_of_DK: yes sir

16:53 blackdog: i mean File class not string

16:53 Lau_of_DK: ImageIcon(Image image)

16:53 Creates an ImageIcon from an image object.

16:53 blackdog: ok, that looks fine to me :/

16:53 Lau_of_DK: Does it work the type of automatically?

16:54 blackdog: yes

16:56 Lau_of_DK: (let [image-holder (ImageIcon. "fia.JPG" "Fia picture")

16:56 icon-label (JLabel. "fia" image-holder)

16:56 ok-button (JButton.)]

16:57 This is whats causing the problem, I have a suspicion that its the icon-label that not getting it

16:57 blackdog: this works for me

16:57 user=> (import '(javax.swing ImageIcon))

16:57 nil

16:57 user=> (ImageIcon.)

16:57 javax.swing.ImageIcon@7f1e1bbf

16:57 user=> (ImageIcon. "my string")

16:57 my string

16:57 user=>

16:57 no description

16:58 actually adding desc doesn't have it throw an err either

16:58 Lau_of_DK: user> (ImageIcon. "fia.JPG" "fiaPicture")

16:58 fiaPicture

16:58 user> (JLabel. "fia" (ImageIcon. "fia.JPG" "fiaPicture"))

16:58 ; Evaluation aborted.

16:59 I dont think the JLabel is understanding that param2 is an Image

16:59 Chouser_: ah, that's probably it.

16:59 Lau_of_DK: Anyway I can enlighten it ?

16:59 Chouser_: You might need a type hint there.

16:59 Lau_of_DK: #^ImageIcon ?

16:59 Chouser_: try it

17:00 rhickey: Lau_of_DK: evaluation aborted is the only message?

17:00 Lau_of_DK: I've never used those before

17:00 icon-label (JLabel. "fia" (#^ImageIcon image-holder))

17:00 That gives me an ImageIcon cast error, cannot be converted to IFn

17:00 rhickey: a call to new is its own type hint

17:01 Lau_of_DK: rhickey, no I get the usual 20 lines of Java trace

17:01 Chouser_: (JLabel. (ImageIcon. "fia.JPG" "fiaPicture"))

17:01 rhickey: Lau_of_DK: don't ignore it, especially the first line

17:02 Chouser_: Lau_of_DK: you mean to be calling JLabel(String�text, Icon�icon, int�horizontalAlignment) ?

17:02 Lau_of_DK: rhickey, first line "No matching cstor found, IllegalArgumentException, 0: ...Reflector.invokeConstructor

17:02 Chouser, yea thats the one

17:02 rhickey: right - have you got the right ctor args?

17:02 Chouser_: well, then you need a 3rd arg that's an int.

17:02 Lau_of_DK: Chouser, the last one you posted worked, but loads no image

17:03 rhickey, Im sure what you mean by ctor arg

17:03 rhickey: constructor argument

17:04 Lau_of_DK: No I didnt. But thanks Chouser it was the last int that did the trick

17:04 I gotta hit the sack - Thanks blackdog, Chouser and rhickey for helping out

17:06 Chouser_: rhickey: did you see that la_mer got Clojure working on .Net via ikvm?

17:06 rhickey: Chouser: yes, very cool

17:07 la_mer: it would be nice if clojure could be made to work around whatever problems ikvm 0.34 has -- that's the last version that can target .NET 1.1.

17:08 rhickey: don't worry, I'm not looking at you for that -- I might try my hand at it :-)

17:08 rhickey: la_mer: to which version of Java does IKVM 0.34 correspond?

17:09 la_mer: rhickey: 0.34 uses the 1.5 versions of openjdk, I believe.

17:09 rhickey: ok, so it should be possible

17:10 la_mer: That's only relevant when you're using ikvm as a runtime, though -- ikvmc will take any java classfiles and deliver a DLL/exe

17:10 I think 0.34's problem is that it's reflection api is slightly broken, FYI.

17:10 s/it's/its

17:11 rhickey: ah

17:11 la_mer: That's why I don't expect anyone else to give a damn :-)

21:57 drewr: Is there a Clojure or Java operator for comparing the order of strings? I.e., (< "0830" "1000")...

22:04 Hm, perhaps that's what compareTo is for.

22:12 slava: most of the time, you don't want lexicographic order on strings

22:16 drewr: Can I cast to an int?

22:19 Chouser: you can get an int by calling (.hashCode "1000")

22:19 ...but it's probably not the int you want for sorting. ;-)

22:20 (Integer. "500") => 500

22:21 drewr: Forgot Integer had a ctor for that.

Logging service provided by n01se.net