nuthole.com "could I form a bronzed statue of you and worship it day and night?"
contact:email
subscribe:feed
2006
Powered by Blosxom
Get Firefox!
geourl
subgenius
spampoison hosting rails

Darksided: The Clarification

posted by jack at 16:49 CET in / music feed

Some people, upon hearing Darksided, wonder what the hell the lyrics are all about, and who the crazy screaming woman is. Though it's already mentioned on the Band of None website, for the sake of completion here I'll tell you to go here for a full exposition.

permalink | digg this | slashdot this | add to del.icio.us | 1 comment (add more!)

Band of None - Darksided

posted by jack at 21:51 CET in / music feed

To my continual surprise, I find that I'm involved in the first teetering baby-steps of a new band. Early days, but we do have a name ("Band of None"), a website, and a first single: "Darksided".





I don't know how to categorize our music so far. Industrial? Techno? Rock? Somewhere around there. Please poke around the website, have a listen, and let us know what you think.

[UPDATE: added inline music player]

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

is that a mod in your pocket?

posted by jack at 12:31 CET in / life feed

I used to be a big Palm user, keeping all my contacts and calendars in sync between my desktop machine and my handheld. Over the years though, I've switched almost exclusively to using a laptop instead of a desktop machine, and always have a bluetooth cellphone with all my contacts in my pocket. The final nail in my Palm's coffin, though, was getting an iPod which took over the last regular use I had for my Palm (Bhajis Loops notwithstanding).

So now that I've got no Palm in my pocket, I've got a new problem. What do I do if I want to just jot down a name, phone number, or URL when I'm on the go? Use my cellphone keypad? Eek. Thanks to a tip from Andy Hunt, I've found an excellent technology: Paper! PocketMod lets you create your own personal folded notepad/calendar/whatever to carry in your pocket. Just pick what you want to have on your pages, and print. An online guide shows you how to fold and cut the paper, and off you go. Normally I never carry a pen or pencil around, but since I started using PocketMods, keeping one in the same place at home where I keep my wallet and keys, I can't help but stick it in my pocket along with a pencil in the morning. Now I can once again capture those important yet fleeting ideas that will surely lead to fame and fortune.

permalink | digg this | slashdot this | add to del.icio.us | 2 comments

building a playhouse

posted by jack at 06:21 CET in / life / pictures feed

Together with my father-in-law, we built a playhouse this summer! Instead of just dumping the pictures into a ready-formatted .mac page template or something, I decided to share them using Tabblo. Click the thumbnail image to the right to get to all the pictures.

All in all, this new Tabblo service is pretty cool. You can upload a bunch of pictures, create a nice layout of your own design (including text boxes of varying sizes), and Tabblo provides slideshows, downloads of the original fullsize images, etc. And of course it's free!

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

pythong

posted by jack at 13:43 CET in / humor feed

I think I can safely call myself a "python programmer". And a "touch typist". And a "good speller". And yet, hardly a day goes by that I don't mistype "python" as "pythong". I nearly did it while typing that sentence. I don't know why, it's just the way it is. At least I can console myself with the knowledge that I'm not alone.

Now I've decided to capitalize on this shortcoming with a novelty product that will surely make me rich. Behold, the PyThong!!!

the pythong Please buy several for yourself and everyone you know. Christmas is just around the corner! Who wouldn't want a PyThong in their stocking?! This is also, of course, the perfect attire for the next pycon or EuroPython conference.

permalink | digg this | slashdot this | add to del.icio.us | 1 comment (add more!)

three cheers for the curmudgeon!

posted by jack at 22:22 CET in / humor feed

As a child, I was often puzzled by the existence of some really lame comic strips in the newspapers. I could not for the life of me imagine why anyone would want to read strips like Gil Thorp, Rex Morgan M.D., or Mary Worth. Compared to the comics I loved best at the time, such as Bloom County and (yes, I'm man enough to admit it) Garfield, these print versions of soap operas just seemed completely useless.

Now I know the ultimate purpose of these comics: to be bitterly, hilariously mocked by The Comics Curmudgeon. This site not only pokes fun at the soap-opera-style comics mentioned above, it also highlights foolishness in Mark Trail, timeless stereotypes in Crock, and fearful grandparenting in Gasoline Alley. Go get your Josh on.

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

fram och tillbaka

posted by jack at 08:46 CET in / creations feed

Last weekend, I took part in a film-making project sponsored by Stockholms Läns Museum and Film Stockholm. Here's what I made. The voiceover is in Swedish, though I may do an English version later as well.

The idea behind the project is to have 100 people living in Stockholm create a digital story about some aspect of their lives. The project is executed entirely on Macs running iMovie. I've used iMovie plenty in the past, but this is the first time I've so heavily abused the Ken Burns effect! See more about the project, and watch other participants' creations, at www.hundrahistorier.se

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

huge volumes of pointless syntax

posted by jack at 14:22 CET in / compute / programming feed

It's high time for the next installment in my irregular series of C++ rants. This time I'm going to talk about expressiveness (or rather, C++'s lack thereof)

Expressiveness indicates a capability to accurately and briefly express something. A human being is considered to be expressive if they are able to speak in such a way that someone listening to them can quickly understand the person's message. A computer language's expressiveness is a measure of how quickly a programmer can write code that is unambiguous and a correct reflection of the design in the programmer's mind.

Let's illustrate this with an example. Imagine we've got a class with an instance variable containing an array (or list, or vector, or what have you) of some other type. We want to give our class a method that takes another array, iterates through all the objects in it, and adds them to its own array. Obviously this is a contrived example, since nearly all container classes in all languages must include functionality for adding the contents of one array to another, but the point here is to demonstrate how a simple iteration is done.

Let's start off with the C++ version, something like this:


class ValueContainer
{
    // a vector containing Value objects
    std::vector<boost::shared_ptr<Value> > m_values;

    void addValues(std::vector<boost::shared_ptr<Value> >values)
    {
        // an iterator pointing at the first value
        std::vector<boost::shared_ptr<Value> >::const_iterator it = values.begin();
        // an iterator pointing at the special "end" value indicating we've reached the end
        std::vector<boost::shared_ptr<Value> >::const_iterator endIt = values.end();

        // step through the entire array
        for (; it != endIt; ++it)
        {
            // add the value to our array
            m_values.push_back(*it);
        }
    }
};

Some of you may be unfamiliar with the boost::shared_ptr stuff in there. The boost project is a sort of proving ground for classes that are probably destined for the standard c++ library in the future, and shared pointers are a very valuable concept that make c++ development a little more do-able, by helping you manage object ownership.

Anyway, that's quite a pile of code, isn't it? All we're doing is walking through a list of things!

Some may balk at this, saying that the boost shared pointers are overkill here. OK, fine, let's take those away, and take away the comments, and stuff all we can into the for, getting this down as tight as we can:


class ValueContainer
{
    std::vector<Value> m_values;

    void addValues(std::vector<Value> values)
    {
        for (std::vector<Value >::const_iterator it = values.begin(); it != values.end(); ++it)
        {
            m_values.push_back(*it);
        }
    }
};

Now let's see how a similar class might look in python:


class ValueContainer:
    def __init__(self):
        self.values = []

    def addValues(self, values):
        for v in values:
            self.values.append(v)

Unlike C++, Python has no free-standing declarations of instance variables--they're defined only as they're referenced inside of methods, and the best practice is typically to provide an initial definition inside the initilializer method __init__ as I've done here.

There are several nice things about Python that this highlights:

  • the syntactic indicator that we're dealing with an instance variable by always prepending self.
  • the more sensible method names in Python's array class compared to C++'s std::vector class (append vs push_back)
  • the values parameter isn't statically typed, so it doesn't need to actually be a standard python array, but can be any class that implements the methods required for iteration
but the big win I want to point out here is really the difference in the for constructs.

Look at the mass of ugliness in the C++ for construct. To start off with, you're forced to declare a variable with a bizarre iterator type. Why should I have to care about that? I'm not using it in any way; that type is completely irrelevant to my code. Later, to iterate I have to use it++, which may not be pointer arithmetic, but at least looks like pointer arithmetic, and that is just so 1985.

Then, take a look at the simplicity of the Python for construct. The designers of Python built iteration right into the language! You simply give for the name of the variable that should be used to hold a value from the array, and the array itself, and off it goes. Behind the scenes, iteration occurs through well-defined methods, and if you're making your own collection class you can define your own iteration scheme, but all of that is completely invisible to a user of the class.

IMHO, this sort of thing is really one of the biggest wins for languages like Python. You get to leave out all sorts of meaningless busy-work, since the language includes useful mechanisms that C-based languages don't, and you are left with the job of programming the actual functionality you're after.

permalink | digg this | slashdot this | add to del.icio.us | 7 comments

Steven Colbert goes to Washington - and kills it

posted by jack at 11:01 CET in / politics feed

This has already been linked-to all over the place, but anyone who already hasn't should go check out Steven Colbert's speech (especially parts one and two; I thought part three kind of fell flat) from the White House Corresponts' Dinner held last weekend. It takes some serious balls to stand there, just a few feet away from ol' monkey-boy, and lower him a notch or ten like that.

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

The Horror of Compile-Time Binding

posted by jack at 20:16 CET in / compute / programming feed

I'm working on this C++ project, and suddenly realize how much we're using the visitor pattern. The point of the visitor pattern is to extract non-core functionality out of data-bearing classes, instead gathering that functionality into a visitor class that knows how to operate on all the data-bearing classes. You do this by making each "visitable" class implement a method that accepts a visitor object, which in turn calls a method in the visitor to do its work, along these lines:


void MyClass::accept(Visitor &v)
{
    v.visitMyClass(this);
}

That way, new visitors can be created to implement new functionality involving visitable classes, without the visitable classes needing to be changed or even recompiled. Here's where the fun kicks in. For each new "visitable" class I add, I need to add a member function for each existing visitor, which means editing dozens of .h and .cpp files, adding a small "visitXXX" member function to each.

The kicker is that most of the functionality we're implementing with visitors consists of either trivial one-liners or empty implementations for most of the visitable types. So we have visitor classes containing dozens of identical member functions. Nothing quite like the joy of editing dozens of files to insert meaningless boilerplate code!

At first I wondered what my co-workers were thinking when they set out on this path, but eventually I came to realize, much to my chagrin, that this is an inescapable reality of C++ programming in many situtations, thanks to the compile-time binding that C++ does. The compile-time binding actually precludes you from doing certain things without this sort of indirection.

To see why this is, first consider an example that demonstrates how things can work in a more full-featured OO language, such as python. Consider the following python program:


class A:
    def emit(self):
        print "Class A"

class B (A):
    def emit(self):
        print "Class B"

a = A()
b = B()
a.emit()
b.emit()
print "-----"
objects = [a, b]
objects[0].emit()
objects[1].emit()
This code snippet defines and manipulates a simple class hierarchy, with B inheriting from A. Common sense tells you what the output of this program may be:
Class A
Class B
-----
Class A
Class B

And your common sense would be right. Whe calling the emit method on the a and b objects, the correct method is triggered and the corresponding class names are output.

Now then, considering the following C++ program:


#include <iostream>
class A
{
public:
    virtual void emit() {
        std::cout << "Class A\n";
    }
};
class B : public A
{
public:
    virtual void emit() {
        std::cout << "Class B\n";
    }
};
int main (int argc, char * const argv[]) {
    A a;
    B b;
    a.emit();
    b.emit();
    std::cout << "-----\n";
    A objects[] = {a, b};
    objects[0].emit();
    objects[1].emit();
    
    return 0;
}

Does your common sense tell you this program should have the same output as the earlier python version? Think again:

Class A
Class B
-----
Class A
Class A

Say what? "But, but, but, I put an instance of B in that array, wtf?" Well, here's where C++'s compile-time binding came and shot you in the foot. Note that C++ doesn't offer any sort of generic array of objects. Whether using a C array as I've done, or a std::vector object, you must indicate the type of the object, in this case the root of our hierarchy, A. C++ then makes use of this type information when your program is compiled to match up the call to emit with the implementation in the named class, rather than the implementation in the derived class you're actually instantiating! Doh!

This has dire consequences for any situation where you've got a collection of objects of varying types. Say you've got a bunch of model classes, and you'd like each class to emit an xml string containing its values. In Objective-C, Python, Ruby, Smalltalk, and probably even Perl and Javascript, this is pretty straightforward; You just give each class a method that emits a string (and, assuming you've got an acyclic directed graph, calls the emitting method in each of its "child" objects). Then you just call the emitting method in the root object, and away you go. For example, once again consider some python:


class RootElement:
    def emitXml(self):
        print "<root>"
        for child in self.children:
            child.emitXml()
        print "</root>"
class SomethingElement:
    def emitXml(self):
        print '<something value="', self.value, '"/>'
class SomeoneElement:
    def emitXml(self):
        print '<someone value="', self.value, '"/>'

r = RootElement()
c1 = SomethingElement()
c2 = SomeoneElement()
c1.value = "first child"
c2.value = "second child"
r.children = [c1, c2]
r.emitXml()
(Note that this code breaks encapsulation quite a bit in setting attributes on the objects, and is not what I'd do in production code. But python lets you do it, and it makes examples short and sweet, so there you have it.)

Now then, that code outputs about what you might expect:

<root>
<something value=" first child "/>
<someone value=" second child "/>
</root>

Simple, right? Well, if you try to do something similar in C++ (or Java for that matter), you'll run into trouble. You can start by giving your element classes a common parent declaring emitXml (don't need to bother with such a thing in python, where method calls aren't bound to implementations until runtime), but as soon as you have something like RootElement maintaining a list of child elements, you'll hit the same snag in our earlier example; the relevant implementations of emitXml will be passed over in favor of the generic implementation in the parent class.

Which is where the visitor pattern comes in. It's basically a kludge to work around the compile-time binding limitation of C++. Even when there are times you'd want to use it in order to extract responsibilities out of a data-bearing class, you still end up with this ridiculous double-dispatch syntax (compare with Objective-C, where you can actually add methods to an existing class by using a category, so you can accomplish the same design feat of grouping functionally-related methods together, yet outside the classes they operate on, without the artifices of the visitor pattern).

The moral of this story is that the visitor pattern is a necessary evil for statically-bound languages like C++. And that if you want to avoid this evil thing, start by avoiding C++. Really, pick up python or ruby or Objective-C or whatever. Really!

[update] fixed some typos, thanks weinholt

permalink | digg this | slashdot this | add to del.icio.us | 7 comments

Here's Where I Tell You What's Wrong With The Music Industry

posted by jack at 23:48 CET in / thinking feed

I've been thinking about this for a while, been meaning to blog about it, and some recent conversations have brought it to the forefront of my mind. Here goes.

Surely no one has missed the fact that the music industry has gone through some changes in the past few years. Things like the iTunes music store have dragged the record labels, kicking and screaming, into the 21st century. Most of them are onboard by now, but there's still an undertone of terror visible in their actions; More and more of the CDs they sell have been whammied so they sometimes won't work on a computer at all. Or, if they do work on a computer, they may install deadly evil mojo on your machine in the process.

The reason for these paranoid practices on the part of the record labels is pretty easy to suss out: For decades, they've built their businesses around selling bits of plastic or vinyl. They've taken for granted that they'll be able to continue doing this forever, and that this will always be their most important source of revenue.

So naturally they're worried about mp3 and similar technologies robbing them of some of their profits. I think it may be instructive to consider what happened around the birth of the recording industry. At that time, many live performers became concerned for their livelihoods, worrying that if people could hear music on demand at any time, they'd no longer bother going to performances, and these live performers would be out of work. Of course, this turned out not to be the case; If anything, recorded music has served to propel any number of performers to a level of fame and fortune that would have been impossible without recordings. I believe that the music industry's concerns about losing revenues due to illegal digital distribution are similarly unfounded.

For one thing, there is a notion that the people who download lots of music illegally are probably the people who also buy some of the largest amounts of legitimate copies of music. Downloading doesn't replace their music-purchasing, but rather enhances it by letting them sample music from unfamiliar artists (potentially leading to future purchases) or downloading unavailable-for-purchase bootleg recordings of familiar artists (which increases the "bonding" between a listener and a favorite artist even more).

Perhaps more importantly, the music industry is sitting on the keys to unlocking its own future potential. For instance: Propelling public awareness of artists through cross-promotion. Let's say you're a big Nine Inch Nails fan, having heard their music on the radio, maybe gone to a show or two, etc. At some point you point your browser at http://www.nin.com, look around a bit at some lyrics and whatnot, and then you end up backtracking and surfing on somewhere else; Your interest in NIN didn't lead to any info about anything non-NIN.

How could this be improved? Well, NIN is currently on Interscope. What if Interscope stipulated that all of its artists needed to provide linkage (in the form of a side-bar, or a dismissable slide-over graphic) to other, similar Interscope artists? Then you might find out about Helmet or Audioslave or, perhaps, some up-and-coming band that you've really never heard of. Some would complain that Interscope infringing on their artists websites would be a terrible, terrible thing, but considering all the other shit they pull on the artists in their stables, this would be pretty minor.

A bigger problem is that relationships between artists come and go. As of this writing, for instance, the above-mentioned Helmet is still listed on Interscopes Artists page, despite the fact that one of the latest entries on Helmet's page mentions that they've left Interscope. Oops! So Interscope's (hypothetical) forced linkage from NIN to Helmet now isn't helping Interscope any more. But... what if it wasn't just Interscope? What if the industry as a whole were presenting interesting ways for listeners to find similar artists? That way Interscope would still benefit from a NIN<->Helmet linkage since in the future, visitors to Helmet's site would still get back to NIN.

Apart from just a plain old list of links between similar bands, things could be user-tailored so that sites would bring to the user's attention news about upcoming local concerts with relevant artists, eventually including (gasp) unsigned artists as well (which the industry as a whole benefits from promoting since one day, presumably, any decent unsigned artist will be under contract with one of the labels).

Now all someone has to do is convince the music industry that I'm right, and implement a solution for them, giving them an offer that's so good they can't say no.

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)

The Best. Mobile. Game. Evar.

posted by jack at 15:42 CET in / compute feed

Since back in the 80's, this funky Welsh dude (complete with an unhealthy fascination with farmyard animals) named Jeff Minter (aka yak) has produced videogames and software toys for the platform du jour, starting with the old Commodore Vic-20 and continuing right up to the current Xbox 360. The hallmark of all his games has been extremely trippy visuals, moreso over time...

Now, one of his latest works, gridrunner++, has been ported to J2ME, which means that you (yes, you!) can run it on your cellphone! OK, not just *any* cellphone, but most of the middling-or-better European-market phones from the past couple years (and probably some of their American counterparts). I bought a copy here, and you should do the same. Even on the tiny screen, this thing is a dazzling display of exploding, twisting, pixel-shattery goodness. You owe it to yourself, I'm sure.

permalink | digg this | slashdot this | add to del.icio.us | 2 comments

The Worst Object-Oriented Language

posted by jack at 22:46 CET in / compute / programming feed

I've been doing object-oriented programming and design since 1994. Most of that work has been centered on Objective-C, with a bit of dabbling in Smalltalk quite some time ago, occasional forays into Java, and increasingly more Python during the past few years. During the past year, I've finally had a reason to get deep into a project with C++, and now I know what I've been missing: A heap of nasty syntax and inflexibility, that's what!

Don't get me wrong, C++ is definitely a lot more powerful than just plain old C, and you can do some clever things with its templates and some other language features (with the caveat that in doing these clever things, you are relying heavily on the compiler doing lots of things that are far from explicit in the code, which is quite different from standard C). My main gripe with C++ is that the object-oriented constructs it provides are really very not suited to the practice of object-oriented programming as it stands today (which may be a subject of future postings here).

On a whim, I recently googled "worst object oriented language", and got some interesting results. This query produced 103 results, which Google whittled down to just 12 after removing what it thinks are probably duplicates. Four of those were essentially the same quote from one article, pasted into different contexts, while the other eight seemed to be unique utterances. In all of these cases, the language being described was (drumroll, please...) yes, C++. At least I'm not alone in feeling this way.

permalink | digg this | slashdot this | add to del.icio.us | 2 comments

pandora

posted by jack at 08:45 CET in / compute feed

My pal James tipped me off to the existence of pandora, which lets you create your own streaming virtual radio station, continually feeding your head with music you like, often things you had never heard of and wouldn't have guessed you would like! The way it works is that you tell pandora the names of some bands you like, and it uses that as a basis to begin choosing songs that it thinks you will like. The "editors" at pandora have listened to thousands of albums, categorized their content by assigning attributes based on the sounds, and put it all in a database. So, if you start off by entering Tiny Tim as your favorite artist, presumably you'd get a stream full of artists who sing falsetto, or play ukelele, or both. [note to self: create Tiny Tim-based pandora station and see what happens]

To top it off, the virtual stations you create can be shared with others! I now submit for your listening pleasure my first pandora-station: rock bastard. It gave James a headache; hopefully you're made of harder stuff.

permalink | digg this | slashdot this | add to del.icio.us | 2 comments

scratch

posted by jack at 10:25 CET in / compute feed

A few weeks ago, I became the proud owner of an iPod Nano. It now accompanies me everywhere. Whether I'm commuting, coding, or cooking, chances are I've got my preciousss in a pocket or otherwise on my person.

The only downside is that the shiny black surface gets scratched insanely easily! When reports first came out about this last fall, I figured it was the whining of some perfectionists. But now that I've got one myself, I've seen the light (and the scratches). I've carried cellphones around for years without this kind of scuffing. I used one phone from June 2003 to December 2005, and that phone looks better than my iPod did after just a week of use! During that week, I either carried it in a soft jacket pocket containing nothing else than the iPod and the headphones, but the surface looks like I've been dragging it behind a car.

Fortunately, I'm a pragmatic person, and I don' t much care how my devices look, as long as they do what they're supposed to. Unfortunately the scratching was beginning to mar the display as well, so I decided to buy some protection in the form of an iSkin Duo. This is a dual-layer silicone "condom" for the iPod. It comes in a range of color combinations, most of them brutally ugly. I chose the brown/orange combo, which I would classify as only "moderately ugly". A hard transparent plastic bit covers the screen, while the click-wheel is covered by a single layer of silicone and an optional thin plastic bit to make the wheel a little smoother. All in all, I'm really happy with this:

  • I can toss my iPod into a pocket without worrrying that it's scratching up even more.
  • The silicone skin makes it a little less slippery, therefore easier to grab and more difficult to drop.
  • The ugliness may prevent would-be thieves from even recognizing the iPod for what it is.
permalink | digg this | slashdot this | add to del.icio.us | 1 comment (add more!)

Universal Christmas Poo

posted by jack at 14:21 CET in / compute / mac feed

Did I release the very first third-party screensaver for Intel Macs? It seems like it! I released the latest version of the Mister Hankey Screensaver way back in November, compiled as a Universal Binary so that it would work on Intel Macs. I didn't have access to a developer Intel Mac, so I had a friend try it briefly and verify that it worked.

Now that Intel Macs are actually available, I checked versiontracker's Mac Intel page to see what else was out there. Imagine my surprise when I found only five other Mac Intel screensavers there, all of them released in the past couple weeks! Google can't seem to find anything else, either.

So, as far as I can tell, Mister Hankey is the first screensaver ever released for Intel Macs by a third party. Hooray!

permalink | digg this | slashdot this | add to del.icio.us | 2 comments

Chomsky on the lack of a war on terror

posted by jack at 14:47 CET in / politics feed

Just read a mercifully short interview with Noam Chomsky. I say "mercifully short" because, as much as I admire the old guy, lots of his writings tend to be long and dense. Good to see a bite-sized piece for a change.

Some salient bits:

A large majority of the population is in favor of a national health care system of some kind. [...] But whenever that comes up [...] it's called politically impossible, or "lacking political support," which is a way of saying that the insurance industry doesn't want it, the pharmaceutical corporations don't want it, and so on.
[...] we are under a rigid doctrine in the West, a religious fanaticism, that says we must believe that the United States would have invaded Iraq even if its main product was lettuce and pickles, and the oil resources of the world were in Central Africa. Anyone who doesn't believe that is condemned as a conspiracy theorist, a Marxist, a madman, or something.
What gives me hope actually is public opinion. Public opinion in the United States is very well studied, we know a lot about it. It's rarely reported, but we know about it. And it turns out that, you know, I'm pretty much in the mainstream of public opinion on most issues.

Pass it along to your conservative friends!

permalink | digg this | slashdot this | add to del.icio.us | 0 comments (why don't you write the first?)



Looking for programming talent that doesn't make you say "WTF!"? Try the hidden network.