#clojure log - Jul 03 2011

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

7:48 Dranik: how to import java.io.File/separator as separator?

7:54 babilen: technomancy: ping (Debian packaging)

8:09 terom: Dranik: I think you can't, but you could always (def separator java.io.File/separator)

8:11 If you (import 'java.io.File) then you can of course use File/separator

8:24 Dranik: thanks!

12:07 technomancy: babilen: bout to head out, but what's up?

12:18 avartanian: I have a quick newbie question.

12:18 How the heck do I load the clojure.contrib.math library?

12:19 I'm doing: java -cp clojure.jar;clojure-contrib.jar clojure.main

12:19 And then (:require clojure.contrib.math)

12:19 But

12:19 java.io.FileNotFoundException: Could not locate clojure/contrib/math__init.class or clojure/contrib/math.clj on classpath: (NO_SOURCE_FILE:4)

12:20 gfrlog: ah ha

12:21 welp...I have no idea why (:require clojure.contrib.math) did that -- I would expect you'd have to (require 'clojure.contrib.math). But anyhow, the other thing that looks strange is that you used a semicolon in the -cp arg instead of a colon. Unless that's a windows thing.

12:22 avartanian: It might be Windows thing.

12:23 With the colon I can't even get the REPL.

12:23 gfrlog: okay. that part is probably right then.

12:24 so I get the same result you do with (:require clojure.contrib.math). It doesn't surprise me at all that it doesn't work, but the error message itself is quite surprising. Regardless, (require 'clojure.contrib.math) works like I would expect, so try that.

12:24 there's a difference between how you use/require/import in a standalone function call versus with a (ns) expression

12:25 so I imagine that's why you were doing it the other way

12:25 actually now that I look a little closer my error message is different from yours, and mine I can make sense out of

12:26 avartanian: user=> (require 'clojure.contrib.math) java.io.FileNotFoundException: Could not locate clojure/contrib/math__init.class or clojure/contrib/math.clj on classpath: (NO_SOURCE_FILE:0)

12:27 gfrlog: it is behaving as if the contrib jar is not on your classpath -- you're sure you got the name right and everything?

12:27 avartanian: Double checking.

12:27 user=> (. System (getProperty "java.class.path")) "clojure.jar;clojure-contrib.jar"

12:28 clojure-contrib.jar is right there in the same folder as clojure.jar

12:28 gfrlog: where did you get these jars?

12:28 avartanian: Downloaded from the Programming Clojure web site.

12:28 Is that my fatal flaw?

12:29 https://github.com/stuarthalloway/programming-clojure/tree/master/lib

12:29 gfrlog: I guess I can try to reproduce then.

12:30 avartanian: Gosh, thank you so much for your help.

12:30 Do people usually rebuild clojure-contrib from source?

12:30 gfrlog: no problem. If I can't figure this out I'll recommend you try leiningen :)

12:31 I use leiningen for all my clojure stuff. So I'm almost never calling "java" correctly, or finding jars

12:32 it has tasks for creating new projects, compiling, launching repls...

12:33 hmm. Requiring works fine for me with those two jars. So I'm not sure what's going on with you :(

12:34 I know very little about java on windows, so if there's some kind of OS difference I'm not really able to guess what it would be

12:34 I wouldn't think there should be though

12:36 avartanian: This is bizarre.

12:36 Ususally I can rename a jar file

12:36 into a zip and crack it open

12:36 but when I try to open clojure-contrib.jar it complains that the file is invalid

12:36 gfrlog: that sounds like a good clue :)

12:37 does windows have any hash function utilities that we can compare with?

12:37 md5? sha1?

12:37 avartanian: Lemme see.

12:39 downloading fciv now

12:41 827c0b06655f06cab6f1c9929ebbf9b9 clojure-contrib.jar

12:41 I believe that's the MD5

12:41 gfrlog: 1ee08937e34732b60ab3b3d975ee1399 clojure-contrib.jar

12:41 fafd2654c66d6299219b56a909326bea clojure.jar

12:41 check your clojure.jar to see if it matches?

12:42 avartanian: Well I'm on version 1.2 of clojure.

12:42 gfrlog: if we both got the jars from halloways git repo, then they should match

12:42 avartanian: Oh my clojure.jar is from elsewhere.

12:43 Not the halloway git

12:43 abdf685c42f362dfe0f36e325b8dc724 clojure.jar

12:43 But it's weird that our MD5s on contrib don't match.

12:43 gfrlog: ah. Could you try using his clojure.jar then? maybe it's some kind of incompatibility...

12:43 avartanian: yes

12:43 trying now

12:43 gfrlog: I don't mean only ever use his jar, but test to see if his two jars work together for you

12:44 the Programming Clojure book is the oldest of the clojure books, and while good, it's a bit dated I think.

12:44 avartanian: e12b163a04a6da02431218c9bb342369 clojure.jar

12:44 gfrlog: that's what people say anyhow. I haven't looked at it for a year or two.

12:45 okay well apparently our md5 programs are different :) that's awesome.

12:45 but try running the repl and requiring using those two jars

12:46 avartanian: Wow

12:46 it's not working

12:46 with just those two jars

12:46 there is something messed up about these jars

12:47 I can't open clojure.jar either.

12:47 Okay, how do people usually get clojure-contrib?

12:47 gfrlog: avartanian: when I use leiningen it fetches both jars for me

12:47 I can unzip clojure.jar just fine

12:48 avartanian: ok

12:48 gfrlog thank you for your help

12:49 gfrlog: sounds like everything you try is weird :)

12:49 you're welcome; sorry about the trouble.

13:16 Is there a subtle reason that #() cannot be nested, or is it just to prevent certain mistakes?

13:18 opqdonut: just to prevent mistakes I guess

13:18 gfrlog: :/

13:19 opqdonut: even if it were allowed it wouldn't be very useful since one couldn't refer to arguments of the outer closure from within the inner one

13:19 gfrlog: you don't always need to

13:19 opqdonut: sure

13:19 gfrlog: (def inc-my-nums #(map #(+ % 1) %))

13:20 opqdonut: (def inc-my-nums (partial map (partial + 1)))

13:20 (or just (partial map inc) ...)

13:20 gfrlog: yes that particular example can be done better :)

13:20 but I just came across this situation

13:20 opqdonut: but of course partial isn't always applicable

13:20 something like "rcurry" from common lisp would be a nice addition

13:21 gfrlog: I wanted a function to transform [{:id 1 :foo "bar} {:id 2 :foo "baz"}] to {1 {:foo "bar"} 2 {:foo "baz"}}

13:21 opqdonut: that is, ((rcurry f x y) z) == f z x y

13:21 gfrlog: which I was going to write as #(zipmap (map :id %) (map #(:dissoc % :id) %))

13:22 but was forced to make the outer one a (fn [r] ...)

13:22 opqdonut: why not (into {} (map #(vector (% :id) (dissoc % :id))))

13:22 er, missing the final argument

13:22 gfrlog: I think zipmap is more natural than into, and either way that'd be the same sort of expression

13:23 opqdonut: ,(let [x [{:id 1 :foo :bar} {:id 3 1 "hello" 2 "hi"}]] (into {} (map #(vector (% :id) (dissoc % :id)) x)))

13:23 clojurebot: {1 {:foo :bar}, 3 {1 "hello", 2 "hi"}}

13:23 gfrlog: opqdonut: but I wanted a function, not just the expression itself

13:23 opqdonut: sure

13:23 gfrlog: so it'd still be nested

13:23 opqdonut: I'm just going off on tangents here

13:24 gfrlog: always welcome :)

13:24 opqdonut: (I dislike using zipmap like that, first taking apart something and then pasting it together again)

13:24 gfrlog: but you're taking things apart too...and creating a bunch of pairs

13:25 opqdonut: yeah but I'm processing one element at a time

13:25 but whatever, this is a minor thing :)

13:26 gfrlog: yeah. For this kind of stuff I'd really like an HOF like (defn map-from-fn [ks f] (zipmap ks (map f ks)))

13:26 opqdonut: I've just seen people use overly complex zipmap invocations

13:26 yeah I usually define something like that

13:26 gfrlog: opqdonut: I used to do it your way. Then I discovered zipmap and decided it felt better that way.

13:26 opqdonut: :)

13:27 gfrlog: I think for the same reason I like (for) more than (map) when I can get away with it

13:27 reabability maybe

13:27 read

13:27 readadility

13:27 reapapility

13:27 * gfrlog stops doing that

15:51 __name__: Haha, classic: http://img264.imageshack.us/img264/1397/lispnd7.png

15:51 jao: Somelauw, as you surely know, there's also (fn [_] nil)

15:52 Somelauw: Yes, but what is the idiomatic one?

15:53 jao: i prefer constantly. i don't know if i'm idiomatic, though :)

15:55 terom: (assoc-in matrix [2 3] nil)

15:55 If the nil is really the thing you want...

16:07 amalloy: yes, assoc-in for sure. but, don't talk about vectors and call them arrays; for arrays you'd use aset

16:08 Somelauw: and for atoms there's reset!, but it's fairly rare that you should actually set an atom without regard to its previous value

16:15 Somelauw: oh thanks, assoc-in is what I should have used.

16:19 Okay, I finally found a use for ->. assoc-in only takes 3 parameters.

16:20 amalloy: Somelauw: bet you a dollar there's a better way to do it than ->

16:22 kephale: chouser: do you work on Gentoo?

16:23 Somelauw: A better way? My code looks pretty beautiful already, I think.

16:25 amalloy: Somelauw: well, you haven't yet said how you're doing it. just that assoc-in takes three params

16:25 so i can't really prove something's better

16:27 Somelauw: amalloy: http://pastebin.com/jr6ZWVkL

16:32 amalloy: Somelauw: well, fair enough. a matter of taste, but consider https://gist.github.com/1062579

16:37 Somelauw: Not bad, but I prefer mine because of readability.

16:39 Also I switch the oldx and oldy, so they are not completely the same.

16:40 amalloy: oh, bizarre. why are you storing the board in row-major order and taking positiong in column-major?

16:41 Somelauw: Well for chess you write e.g. e1 so the horizontal thing comes first.

16:42 But when defining my var called initial-chess-board, it is easier to define it row after after.

16:42 amalloy: Somelauw: i'd transpose the initial-board once at definition time, rather than every time you use it

16:42 Somelauw: Because I have functions like (king-row player) and (pawn-row player)

16:43 amalloy: hm

16:43 AWizzArd: I have a question for the Java/OOP experts here. Clojures proxies can not call overwrite protected methods. Clojures defrecords and deftypes can work with protocols and interfaces. So, in general Clojure heavily encourages Java APIs to do as much as possible with interfaces, instead of inheritance and methods in classes. My question is: why?

16:44 An example: In Java I define a class A with the methods m1 to m9. Now someone can create a proxy instance 'p' of my class and provide an implementation for m1. For the other 8 methods no implementation is given. But I am still able to call .m2 to .m9 on p.

16:44 jsnikeris: Just downloaded lein, and I'm getting a no class def found error: http://pastebin.com/EChCqUE8. What am I doing wrong?

16:45 AWizzArd: If I reify an interface, then where do the default implementations m2-m9 come from?

16:45 Maybe amalloy and dnolen know about it? :)

16:46 amalloy: AWizzArd: interfaces don't get default impls

16:46 AWizzArd: exactly

16:46 So why does Rich encourage interfaces anyway?

16:46 dnolen: AWizzArd: inheritance is not worth the trouble, http://www2.parc.com/csl/groups/sda/projects/oi/towards-talk/transcript.html

16:46 AWizzArd: It would require a totally untypical Java programming style to create APIs that are nicely usable from Clojure.

16:47 dnolen: AWizzArd: that's why detype and defrecord and protocols are not about interop ... at all

16:47 amalloy: AWizzArd: a lot of people encourage programming to interfaces in java as well

16:47 AWizzArd: dnolen: is the "that's why" referring to your link?

16:48 dnolen: AWizzArd: yup

16:48 AWizzArd: amalloy: yes, and I don’t argue against it. I just would like to 1) understand why (hopefully dnolens link will help) and 2) have a way that I can suggest to Java guys, what design pattern they can use to end up with code that is nicely usable from Java *and* Clojure.

16:49 dnolen: AWizzArd: Clojure and Java are philosophical odds, thus we have real interop features ... gen-class & proxy.

16:49 AWizzArd: Rich must have had good reasons to do it the way he did, and I am not criticizing it. But currently I am writing some libs against some Java libs and am confronted from time to time with an API where they want to create an anon subclass and overwrite some methods.

16:49 amalloy: AWizzArd: http://pragmaticjava.blogspot.com/2008/08/program-to-interface-not-implementation.html is a random sample i found while searching for "java program to interface"

16:50 jsnikeris: answering my last question: /usr/bin/java was pointing to some other, non-sun java

16:51 amalloy: part of the problem is that it's so *easy* in java to use concrete inheritance in ways that create maintenance nightmares later

16:51 AWizzArd: dnolen: proxy is great, but it won't let me overwrite protected methods. When I ask the implementors of Java libs they tell me it would be unclean to make their protected methods public.

16:51 So that would mean I have to use AOT via gen-class, which I try to avoid.

16:52 dnolen: AWizzArd: Clojure does it best to work with Java's messes w/o adopting bad ideas.

16:53 AWizzArd: dnolen: after I understand why the clojure way is better I still need some concrete suggestions for the Java guys. When I file Jira issues and complain this is not nice, but when I offer them some solutions it would be much more probable they will implement that, and thus make their lib much more usable from Clojure.

16:55 dnolen: AWizzArd: I'm beginning to think such things are worth the effort. Inheritance sucks, but if that's the best abstraction you have, you're going to use it because it is powerful and it's better than nothing. Trying to convince people otherwise won't help because they don't have better tools. Avoiding inheritance in Java is a big pain in the arse.

16:55 not worth the effort.

16:56 AWizzArd: Maybe that is what they will decide. In that case I will have to use gen-class or write some Java wrappers into which I can inject my Clojure fns.

16:56 In the end interfaces only serve the purpose to pass around function objects.

16:56 Not closures even, but code.

16:57 It is just the model for default implementations that brings in the problems. One example that I saw today: http://fxexperience.com/2011/07/worker-threading-in-javafx-2-0/

16:57 There is the headline "Service" about in the middle of the page, and it provides a code example where they implement a protected method. I can not do this with a proxy.

17:00 dnolen: If Java was Objective-C + final, everyone would be a lot less brainwashed.

17:01 AWizzArd: hmm

17:01 Didn't Apple implement its iTunes server software in Java?

17:01 dnolen: Java is basically a crappy Objective-C IMO.

17:02 amalloy: AWizzArd: interfaces can be closures

17:02 ignoring java's atrocious syntax for it

17:02 or rather, implementations of interfaces can be closures

17:03 AWizzArd: amalloy: ah yes okay, with some final keywords in Java I think, something like that.

17:33 pcavs: What's the current stable release of clojure and contrib?

17:33 1.2.1 for core, and 1.2.0 for contrib?

17:33 amalloy: yes

17:34 pcavs: thanks

18:26 nathanmarz: technomancy: hey, i noticed you changed how "native-path" works in leiningen

18:27 technomancy: i was using that for zeromq/jzmq, i was wondering what your suggestion is for moving to the new native deps model in leiningen

20:11 paraseba: In clojure.java.jdbc there is a transaction function, which is supposed to rollback if the passed body throws an exception, but it only does that in case of an Exception, not any Throwable. What's the rationale behind this?

20:11 I'd want my transaction rolledback in case of any errors

20:12 seancorfield: maybe you can explain me this?

20:53 amalloy: paraseba: catching Errors is generally a bad practice. i'm not saying it's wrong all the time, but Errors are often unrecoverable anyway

20:53 eg, "You ran out of heap space! I can't even allocate memory to throw an exception!"

20:54 paraseba: but, even in the worst conditions, shouldn't we try to rollback the transaction? is not better that commiting in this unexpected error condition?

20:55 we can then rethrow the Throwable, after trying to rollback

20:55 lucian: paraseba: i don't think the db will commit if it gives you an error

20:55 and as amalloy, errors like OOM are best solved with exit()

20:55 paraseba: lucian: it will ... jdbc is catching Exception and rolling back in that case .... but it commits in a finally

20:56 so, if you have an Error thrown, it will commit

20:56 I guess that's more surprising than a rollback

20:57 the logic is .... (try do-your-thing (catch Exception roll-back) (finally commit))

20:57 lucian: paraseba: well, then maybe you don't want to commit in finally?

20:57 paraseba: I don't, not if I got an Error

20:58 amalloy: lucian: i think he's upset that a library he's using is committing on error

20:59 paraseba: amalloy: I can solve it easily by wrapping my operations in a catch Throwable -> rollback -> rethrow, but I think it's not the right behavior for the library

20:59 I would expect a commit only if the block ended without any kind of exceptions or errors. don't you agree ?

21:01 amalloy: paraseba: meh. all kinds of weird stuff can happen if an Error occurs; i wouldn't be entirely certain that an attempt to "recover" makes things worse due to some weird program state caused by the Error. i mean, my completely-unresearched opinion is that catching Throwable would be better, but you can't really rely for your program's correctness on anything that happens after an Error

21:02 paraseba: but, we are forcing a commit after an Error

21:04 the usual logic should be .... (do do-your-thing (commit)) if do-your-thing throws anything ... no commit is done. Puting a commit in a finally enforces the commit, even after Errors

21:06 amalloy: yeah, i think i agree

21:08 paraseba: amalloy: ok, I'll report an issue, thanks

21:18 jsnikeris: Anyone familiar with enlive/compojure? I'm trying to find a way to have my template sources (HTML) look like an example page when opened directly through my file-system. And then when my app serves them, they will of course be customized. Does that make any sense?

21:20 The idea being that a designer could create the templates w/out actually having to run the app, and then they could be simply dropped in my resources directory unmodified.

21:22 Nikelandjelo: I have test web application with ring. It contains index.html file. How can I serve this static file, if I'm going to create war file and deploy it?

21:23 ihodes: Nikelandjelo: wrap-file middleware

21:23 jsnikeris: not quite sure what you're asking

21:24 jsnikeris: what woud need to change each time? you should be able to open a plain HTML file via your fs...?

21:24 jsnikeris: right, but the images, stylesheets, etc won't show up

21:25 ihodes: jsnikeris: ah that's what you mean. yeah that's a pain. you can use relative paths to your FS when you're hard-coding them, and then have envlive replace them with relative paths for your web-app. make sense/

21:25 ?

21:26 jsnikeris: ihodes: I'm glad you understood that, because I had a hard time figuring out how to explain the problem

21:27 ihodes: jsnikeris: haha, well i think you got the point across. did i? does that make sense?

21:27 jsnikeris: ihodes: yes I understand. it looks like I can just tell enlive to modify every "src" attribute I see, and remove the initial relative path

21:28 ihodes: jsnikeris: that should work, for sure

21:28 jsnikeris: I tried defining a route: (route/resources "../public/")

21:28 but that didn't seem to work

21:29 <img src="../public/images/plus_icon.png" alt="Plus button"/>

21:29 ihodes: i'm not familiar with compojure, i've used moustache some though. it seems wrong to use crgrand's lib for one thing but not th=e other ;) (he did moustache & enlive)

21:30 jsnikeris: hmm, I haven't really checked out moustache

21:30 good experiences with it?

21:31 ihodes: jsnikeris: absolutely. there's a nice overview of the whole stack by brehaut; have you seen it?

21:31 jsnikeris: http://brehaut.net/blog/2011/ring_introduction

21:34 jsnikeris: ihodes: have not. thank you

21:34 ihodes: jsnikeris: that should get you started. similarly, lauj wrote a ncie overview of the stack a while ago. it's has some more example code than brehaut's, but they're both definitely worth a look.

21:35 jsnikeris: http://bestinclass.dk/index.clj/2011/01/building-a-social-media-site.html

21:38 jsnikeris: ihodes: great, thanks for the help.

21:38 ihodes: jsnikeris: no problem at all; enjoy! it's a ton of fun to write, and once you get the hang of it it moves very quickly.

22:04 amalloy: hiredman: http://groups.google.com/group/clojure/browse_frm/thread/1971db3689f631ef sounds like exactly the kind of post you were talking about the other day. someone assign him a contrib library

22:13 Nikelandjelo: I have war file, containing "WEB-INF" dir (with all code) and "static" dir" containing "index.html" file. Ring handler has middleware "wrap-file" with argument "static". When I try to deploy this war on jetty and load page, it throws "java.lang.Exception: Directory does not exist: static". How can I fix it?

22:52 xiaolongxia: Hello, I have a young friend who I am teaching about programming/computers for the first time. I am setting him up an Ubuntu workstation and I am trying to decide on languages. I love the SICP based courses like this one: http://www.youtube.com/watch?v=GAHA0nJv8EA&playnext=1&list=PL9EE9B6729909489D

22:52 but I'd rather teach him clojure right from the start

22:53 does anybody have a recommendation on material for teaching somebody clojure as a very first programming language?

23:00 amalloy: xiaolongxia: i know there have been efforts to port SICP to clojure

23:02 ihodes: xiaolongxia: there probably isn't a great way to do that without considerable oversight. i'd recommend sticking with racket/scheme, honestly, and i think your friend wouldn't have much trouble transferring those ideas to clojure once s/he got to that point

23:03 Scriptor: xiaolongxia: at what level is your friend mathematically? It's often useful to tie ideas from it to programming

23:04 lucian: xiaolongxia: even if your friend were to keep using racket, it would be little loss. it's also a very nice language :)

23:13 pdk: scheme is good for not really overwhelming a new coder

23:13 perhaps aside from when you try to learn continuations

23:13 really effective clojure coding is probably best learned by already having some background in lisp and java

23:14 plus you're learning new stuff like concurrency constructs, lazy evaluation, immutability, explicit TCO, java interop considerations etc right away

23:22 xiaolongxia: Scriptor: sorry for the delay in response. my friend graduated high school an average level mathematically and has not taken any college level mathematics

23:23 Scriptor: xiaolongxia: that's good, the functional style may seem more natural to him

23:24 I used Haskell as pseudocode while trying to teach my friend to to recursion in Python

23:24 never thought I'd see thath happen

23:25 xiaolongxia: the idea here, is to just get his feet wet and see if he has an interest. the only thing i'm worried about .. is with clojure at least i could show him practical applications quickly

23:25 like deploying to GAE using compojure+enlive to write a webapp

23:26 lucian: xiaolongxia: if your friend has little to no programming experience, he might prefer Python fist, instead

23:27 xiaolongxia: lucian: i'm really of the opinion that clojure will be a viable career option in a couple years, in the way that ruby/python are now. I'm not sure if I want to start them thinking in python/ruby when they could learn first in LISP

23:28 lucian: xiaolongxia: as you wish. it is however less likely that a "layman" will hate Python than a Lisp

23:28 I'm saying this as a Python developer that really likes several lisps

23:29 Scriptor: lucian: I'd think experienced imperative programmers are more likley to hate lisps

23:29 xiaolongxia: i generally agree with Scriptor

23:29 amalloy: hugod, technomancy: either of you give me a hand getting marmalade installed? i have package.el, but the add-to-list expression at http://marmalade-repo.org/ is barfing

23:29 Scriptor: python just seems intuitive once you're used to it, but it's not all that much better when you have no experience

23:30 xiaolongxia: also, i just feel like 'from scratch' LISP is a lot easier to grasp than python/ruby/et al

23:30 lucian: Scriptor: perhaps to your first assertion. not sure about the second

23:30 anyway, he's your friend xiaolongxia :)

23:30 technomancy: amalloy: http://code.google.com/p/marmalade/issues/detail?id=20

23:30 xiaolongxia: thanks for the input guys

23:32 amalloy: technomancy: do i have to have emacs 24? (require 'package) and (package-initialize) both succeed fine (and have been in my .emacs for ages), but i still can't add the marmalade repo

23:32 technomancy: amalloy: you can use it with http://bit.ly/pkg-el23 but not with the one from tromey.com

23:33 I have been bugging tromey for like six months to update the version of package.el on his site; no luck. =(

23:36 amalloy: man, i have all kinds of weird crap from when i installed emacs and didn't know how it, or clojure, worked

23:37 technomancy: can i just replace .emacs.d/elpa/package.el, or do i have to do something more exciting?

23:37 i'm afraid to touch this mess

23:37 technomancy: amalloy: that should be fine

23:38 you should check out justinlilly's Seajure hackfest scripts for a "minimum viable clojure emacs" setup if you want to sort things out and start from scratch

23:43 amalloy: technomancy: link? i seem to have messed things up anyway, may as well try a clean start

23:45 technomancy: https://github.com/Seajure/emacs-clojure-vagrant

23:54 alandipert: technomancy: that's awesome

23:57 technomancy: alandipert: yeah, no more excuses!

23:58 hugod: should be able to do one of those with pallet very shortly

23:58 technomancy: hugod: that would be pretty cool

23:59 does jclouds hook into the vbox API?

Logging service provided by n01se.net