<?xml version="1.0"?>
<rss version="2.0">
  <channel>
    <title>apenwarr - Business is Programming</title>
    <description>apenwarr - Business is Programming - NITLog</description>
    <link>http://apenwarr.ca/log/</link>
    <language>en-ca</language>
    <generator>NITLog</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title>A bit more language meditation</title>
      <pubDate>Sat, 24 Jul 2010 07:34:01 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201007#24</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201007#24</guid>
      <description>&lt;p&gt;
After the last couple of bits on C++, I thought I would offer something a
little more melodramatic: human languages, as experienced in Montreal.  Back
in 1887.
&lt;p&gt;
&lt;div align='center'&gt;&lt;img
src=&quot;http://farm3.static.flickr.com/2167/2864820617_86e5cdbfd3.jpg&quot;&gt;&lt;br&gt;&lt;font
size=-1&gt;Old Montreal, 1887, via &lt;a
href=&quot;http://www.flickr.com/photos/museemccordmuseum/2864820617/&quot;&gt;the
McCord Museum's Flickr Feed&lt;/a&gt;&lt;/font&gt;&lt;/div&gt;
&lt;p&gt;
Notice anything funny about this picture?
&lt;p&gt;
I'll give you a hint: Montreal is a primarily French-speaking city.
Looking at the 2006 census, 13% of the population spoke English as a
first language, compared to 54% with French as a first language.&lt;sup&gt;1&lt;/sup&gt;
&lt;p&gt;
...
&lt;p&gt;
...
&lt;p&gt;
...Yet every single sign in that photo is in English!  If you looked at the
same street today, you would see every single sign is in French.&lt;sup&gt;2&lt;/sup&gt;
&lt;p&gt;
Why?  Because of &lt;a
href=&quot;http://en.wikipedia.org/wiki/Charter_of_the_French_Language&quot;&gt;Bill
101&lt;/a&gt; from 1977, informally known as the Quebec &quot;language law.&quot;  Among
other things, that law says any public sign has to
be primarily in French; no other language can be &quot;more prominent&quot; than
French.
&lt;p&gt;
The mere existence of the language law is, itself, fascinating.  It's a
flagrant violation of the free speech rights guaranteed by the Canadian
Charter of Rights and Freedoms.
&lt;p&gt;
But Canadians always hedge their bets, 
so in addition to free speech, the Charter of Rights and Freedoms
&lt;i&gt;also&lt;/i&gt; has a section called the Notwithstanding Clause.&lt;sup&gt;3&lt;/sup&gt; That
clause basically says the government can enact any laws they want that
violate your rights, as long as they comply with a few basic rules, such as
refreshing said laws every few years.  (Unlike other Canadian laws,
rights-violating ones expire automatically.)
&lt;p&gt;
As you might imagine, laws that very literally violate
human rights can cause a bit of a fuss.  This one certainly does - and it
has continued to do so since it was first brought in.  The need to refresh
it every few years guarantees that it gets back into the news every few
years, which is both healthy and stressful.
&lt;p&gt;
I'm a native English speaker myself, so this law comes down to racism against
me.  But you know what?  I think it's a good law.  54% of Montrealers speak
French as a first language; almost all the rest (even me) can speak at least
basic French when necessary.
&lt;p&gt;
As the story goes, the reason the rule was needed in the first place was
this: while almost every French speaker had learned basic English - after
all, the people bordering Quebec in every direction are largely anglophone,
so there are lots of chances to learn - the much smaller English population
didn't bother to learn French.  Because if all the French people are willing
to speak English anyway, why bother?  And if you're making a sign - even if
you're a French person making a sign - are you going to make one that 54% of
people can understand, or one that 99% of people can understand?  That's
right.  If you're a wise French business owner serving primarily French
customers, you'll make your sign in... English.
&lt;p&gt;
Those lazy English people have a point.  It really is a lot of work to learn
French, just so you can speak French in this tiny little enclave of
non-English on a whole continent of English.  I find it completely
believable that English people are so lazy; my own crappy French skills are
testament to that.  And quite simply, Quebec's French speaking majority
called us on it.  They demanded justice: they demanded the right to be
served in the language of the majority.
&lt;p&gt;
And in order to give people that right - a right &lt;i&gt;not&lt;/i&gt; guaranteed by
the Charter of Rights and Freedoms - we had to violate another right,
namely, the right &lt;i&gt;not&lt;/i&gt; to talk to people in French.  If it weren't for
the magic of the Notwithstanding Clause, the government would be enforcing
civil rights...  but the wrong ones.
&lt;p&gt;
By the way, if you're American, and you come to Montreal and people pretend
they can't speak English, you're absolutely right: they &lt;i&gt;are&lt;/i&gt;
pretending.  Because you just rudely jabbed them with hundreds of years of
cultural history.&lt;sup&gt;4&lt;/sup&gt; (Note: it's not a pretense in other parts of
Quebec, where people often speak exclusively French.  And obviously
&lt;i&gt;some&lt;/i&gt; people in Montreal really don't speak English, but it's fewer
than it seems.)
&lt;p&gt;
So what does all this have to do with programming?
&lt;p&gt;
Well, about that C or C++ or Java.  Do you really use it because it's better?  Or
because that's the one thing &lt;i&gt;everyone&lt;/i&gt; can understand, even though
it's not actually the best choice for &lt;i&gt;most&lt;/i&gt; people?  If someone made a
law forcing everyone to write stuff in a particular language - say,
Objective C - in order to prevent the oppression that is, say, Flash - is
that a violation of your freedoms or is someone out there actually
protecting you?
&lt;p&gt;
Okay. It's a stretch.
&lt;p&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;p&gt;
&lt;sup&gt;1&lt;/sup&gt; I tried to look at the &lt;a
href=&quot;http://www.statcan.gc.ca/pub/98-187-x/4064824-eng.htm&quot;&gt;1861 census&lt;/a&gt;
(okay, it's a few years off, but whatever), but the statistics defeated
me. They weren't surveying people's mother tongue at the time,
though they did survey people's birthplaces.  At least 48% of the population
at the time was of &quot;Canadian - French origin&quot; birth, with about 26%
from Britain/Ireland/United States.  However, that doesn't account for an
additional 25% of &quot;Canadian - Not of French Origin.&quot;  How much of that is
anglophone?  I don't know.  Perhaps there were more anglophones than
francophones in Montreal back in 1861?  I don't know.  How did it change by
1887?  I don't know.  This is the sort of information I would like to
retrieve from &lt;a
href=&quot;http://www.wolframalpha.com/input/?i=population+of+montreal+in+1887&quot;&gt;Wolfram
Alpha&lt;/a&gt; if only it weren't a useless piece of junk.
&lt;p&gt;
&lt;sup&gt;2&lt;/sup&gt; You would also notice that Montreal's winter road conditions
are about the same as ever.
&lt;p&gt;
&lt;sup&gt;3&lt;/sup&gt; There's also the &quot;Limitations Clause,&quot; which says the
government can violate your rights, but only if they're consistent and
there's a good reason.  And don't do it any more than necessary (&quot;minimal
impairment&quot;).  From the outside, it's hard to believe weird stuff like this
works, but the emphasis on &lt;i&gt;using power responsibly&lt;/i&gt; instead of
&lt;i&gt;blindly following the letter of the law&lt;/i&gt; is what Canada is all about.
&lt;p&gt;
&lt;sup&gt;4&lt;/sup&gt; Tip: I warn my American friends who visit Montreal that one
simple change in behaviour will make your experience vastly more enjoyable. 
When you start a conversation, any conversation, just saying hi in a store
or ordering in a restaurant - do your utmost to start it in French.  You
know, Bonjour, parlez-vous anglais, mispronouncing stuff off the French side
of the menu, whatever.  It doesn't matter if you suck at French.  You
probably won't get more than 5 words out before the person switches to
flawless English.  Why?  Because you acknowledged that they have rights. 
Imagine if some people from France flew to New York, walked into a
restaurant, and refused to speak anything but French.  Would you think that
was cute?  Acceptable?  Remotely reasonable?  Of course not.  You'd think
they were idiots.  But if you know some French, and they came in and tried
their best at English, but had a terrible accent and awful grammar, you'd
switch to French as a favour to them.  Because they're not being idiots, and
you're a nice person.  Etiquette really is that easy.
      </description>
    </item>
    <item>
      <title>How to design a replacement for C++</title>
      <pubDate>Thu, 22 Jul 2010 16:19:54 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201007#21</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201007#21</guid>
      <description>&lt;p&gt;
My &lt;a href=&quot;http://apenwarr.ca/log/?m=201007#18&quot;&gt;last article on the
ugliness that is C++&lt;/a&gt; didn't actually receive this complaint, but it
should have: I offered a lot of criticism, but no &lt;i&gt;constructive&lt;/i&gt;
criticism.
&lt;p&gt;
I feel a little guilty about it, so let me try to resolve that here with
some actual, constructive advice to language designers, for anyone who cares
to listen.  (Maybe nobody cares to listen, and in fact this will be much
less interesting than the blind ranting of my last article.  Too bad.  Stop
reading now if you're bored.)
&lt;p&gt;
The first thing you need to know about C/C++ is that &lt;b&gt;they're only barely
worth fixing anyway.&lt;/b&gt;
&lt;p&gt;
C has too few features, and C++ has far too many awful ones.  Reasonable
people might disagree on which features C is missing and which C++ should
lose.  But most people would agree at least that C could be usefully
extended, and C++ could be usefully simplified (and maybe have a few
cleanups, like my earlier suggestions of operator[]=, a sensible method
pointer, and sensible standard strings).
&lt;p&gt;
We also know that neither change will happen.  The C people, having seen
what happens when you extend your language willy-nilly (ie.  C++) are
deathly afraid of it and will never ever change again.  The C++ people are
well set on their path (ie.  ultimate salvation is right around the corner
if we can just add a little more crack to our templates) and will never let
it go.
&lt;p&gt;
But anyway, that doesn't really matter.  C and C++ both get the job done in
their respective niches.  And those niches are shrinking dramatically.  Once
upon a time, you'd surely write all your apps in C or C++; nowadays, almost
everything is better off written in a language with more built-in stuff.  My
personal tool of choice nowadays (when appropriate; I'll get to that in a
minute) is python for most stuff, with C modules added on for the parts that
have to be fast.  It works excellently, as judged by my favourite metrics of
fewer lines of code, increased readability, and maximum performance.
&lt;p&gt;
You might prefer ruby or C# or something intead of python.  That's fine,
although python seems to be the winner so far when it comes to a super-easy
and efficient C extension system.  (C#, including mono, makes me especially
angry because C extensions often run &lt;i&gt;slower&lt;/i&gt; than native C#.  There's
a massive and stupid overhead required to escape from the runtime down into
native space and it often outweighs the speed gained from C.  Duh.  In
python the overhead of calling into a C module is essentially zero.)
&lt;p&gt;
To a large extent, the reason you can get away with using &quot;higher level&quot;
languages like python or ruby or C# is that computers have gotten faster and
have a lot more memory than they used to.  You need the faster computer to
run an interpreted language, and you need more memory because you have
garbage collection instead of manual memory management.  But we've got the
horsepower now.  Might as well use it.
&lt;p&gt;
That means C and C++ are on the decline and they're just going to get
smaller.  Good.  The world will be a better place for it.
&lt;p&gt;
But there will always be programs that have to be written in a language like
C and C++.  That includes kernels, drivers, highly performance-sensitive
code like game engines, virtual machines, some kinds of networking code, and
so on.  And for me in particular, it also includes new plugins to existing
C-based legacy systems, including Microsoft Office.
&lt;p&gt;
These programs are never going to go away.  So deciding that they will,
forever, have to suffer with the limitations of either C or C++ is kind of
disappointing.  And yet there is still no language - not even the hint of a
beginning of a language - that can seriously claim to replace them.  Here
are the key &quot;features&quot; you will absolutely need to avoid if you want any
chance at replacing C.
&lt;p&gt;
&lt;b&gt;Things you absolutely must not do if you want to replace C&lt;/b&gt;
&lt;ol&gt;
&lt;p&gt;
&lt;li&gt;Do not remove the ability to directly call into (and be called by) C and
ASM without &lt;i&gt;any&lt;/i&gt; wrapper/translation layers.  When I want to call
printf() from C or C++, I #include stdio.h and move on with my life.  No
other language makes it that easy.  None.  Zero.  Do not be those other
languages.
&lt;p&gt;
&lt;li&gt;Do not remove the cpp preprocessor.  Look, I realize you are morally
opposed to preprocessors.  Well fuck you too.  Your moralizing is getting in
my way.  If you take it out, I can't
#include stdio.h, and I can't implement &lt;a
href=&quot;http://apenwarr.ca/log/?m=200708#13&quot;&gt;awesome assert-like
macros&lt;/a&gt;.  (&lt;b&gt;Note: see update below.&lt;/b&gt;)
&lt;p&gt;
&lt;li&gt;Avoid garbage collection.  Garbage collection is fine as a concept, but you
will never, ever, be able to write a good kernel if you try to use garbage
collection.  This is non-negotiable.  Also, plugins to existing C programs
won't fly with garbage collection, because you won't be able to usefully
mark-and-sweep through the majority of non-garbage-collected memory, and you
can't safely pass gc'd vs.  non-gc'd memory back and forth between C and
your language.  Maybe your language can have &lt;i&gt;optional&lt;/i&gt; garbage
collection, but optional has to mean &lt;i&gt;globally disabled across the entire
executable&lt;/i&gt;.
&lt;p&gt;
&lt;li&gt;Avoid mandatory &quot;system&quot; threads.  If you're writing a kernel, you're
the guy implementing the threading system, so if your language requires
threads, you're instantly dead in the water.  Garbage collection often uses
a separate mark-and-sweep thread, which is another reason gc just isn't an
option.  But it's even more insidious than that: what happens when you
fork() a program that has threads?  Do you even know?  If the threads were
created by the runtime, will it be sane even 1% of the time?  You can't
invent Unix if you can't fork().
&lt;p&gt;
&lt;li&gt;Avoid a mandatory standard library.  People can - and do - compile
entire C programs without using &lt;i&gt;any standard library functions at
all&lt;/i&gt;.  Think about a kernel, for example.  Even memory allocation is
undefined until the kernel defines it.  Most modern languages are integrated
with their standard library - ie.  some syntax secretly calls into
functions - and this destroys their suitability for some jobs that C can do.
&lt;p&gt;
&lt;li&gt;Avoid dynamic typing. Dynamic typing always requires some sort of
dictionary lookups and is, at best, slightly slower than static typing.  To
replace C in the cases where it refuses to die, you can't have a language
that's &lt;i&gt;almost&lt;/i&gt; as fast as C.  It has to be &lt;i&gt;as fast as C&lt;/i&gt;. 
Period.  Google Go has some great innovations here with its static duck
typing.  Objective C is okay here because the dynamic typing is optional.
&lt;p&gt;
&lt;li&gt;Avoid support for exception handling.  It's just too complicated, and
moreover, C people just hate exceptions so they will hate you, too.
And since C doesn't know about exceptions, you will make a mess
when C calls you, then you throw (but don't catch) an exception.  Just leave
it out.
&lt;p&gt;
&lt;li&gt;Do not make it harder to do things in your language than they would be
in C.  Maybe this isn't even worth mentioning.  But the upper bound on the
lines of code it takes to do something should be whatever it would take in C. 
Making your language backward-compatible with C is one way (not the only
way) to achieve this.
&lt;/ol&gt;
&lt;p&gt;
All this sounds terrible, right?  Why even bother if you can't have these
obvious features?  But actually, there are a bunch of things you
&lt;i&gt;can&lt;/i&gt; add and make things much, much better than C without making your
language unacceptable in C's niche.
&lt;p&gt;
&lt;b&gt;Things you can add to your language to make it better than C without ruining your chances to replace it&lt;/b&gt;
&lt;ol&gt;
&lt;p&gt;
&lt;li&gt;Deterministic constructors/destructors (RAII).  This is, quite probably,
my favourite feature of C++ and the primary thing that makes me hate going
back to C.  (The lack of it is also what makes me hate almost every other
high-level language.  Python, thankfully, has this, although they claim that
it's an implementation detail that could go away at any time.  And
IronPython can't do it.  Bastards.) Deterministic constructors and
destructors make smart pointers and automatic refcounting possible (and
delightful!) and let you write things in one line of C++ that would take 10
lines of C.  No exaggeration.  And it compiles down to the same thing that C
would, so there's no runtime cost.
&lt;p&gt;
&lt;li&gt;Closures and anonymous functions.  In fact, &lt;a
href=&quot;http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10&quot;&gt;Apple
has already added these in an incompatible variant of C&lt;/a&gt;.  Maybe you like
them, maybe you don't, maybe you think they're God's gift to programming and
any language without them is an infidel.  But adding them would be harmless,
anyway.  (&lt;b&gt;Update 2010/07/21:&lt;/b&gt; I mean harmless in that it wouldn't
bloat the compiled code; it compiles down to the same ASM as the
equivalent verbose C code, and if you don't use it, you don't pay for it.)
&lt;p&gt;
&lt;li&gt;Implicit user-defined typecasts.  These are a tricky feature of C++ and
some C people hate them because they hide stuff they think should be
explicit.  But you need this if you want to implement non-gross smart
pointers and user-defined string objects.
&lt;p&gt;
&lt;li&gt;Operator overloading.  You have to be seriously tasteful about this one. 
If you don't think you can handle the pressure, leave it out.  But in the
name of God, at least make operator== do something sane by default.
&lt;p&gt;
&lt;li&gt;Automatic vtable generation.  It doesn't have to be full-on OOP, and you
don't need multiple inheritence and any of that stuff.  But a huge number of
lines in C programs are taken up declaring things that are basically
vtables.  Make it better.  Google Go has some great ideas here.  This one
feature is probably the only good thing about Objective C.
&lt;p&gt;
&lt;li&gt;Some sort of generics so you can make type-safe containers.  Note, I'm
not saying &lt;i&gt;templates&lt;/i&gt; here.  C++ has made templates a dirty word; you
want to copy precisely none of their template stuff.  But C# (up to, but not
including, C# 4.0) has some very nice (and highly optimizable in native
code) generics ideas that you can steal.  Also note: I'm not saying
generics are &lt;i&gt;necessary&lt;/i&gt; in a language that replaces C.  C doesn't have
them and it survives.  Most attempts at a C replacement leave this out of
version 1 and add it to version 2, and that's perfectly okay.
&lt;p&gt;
&lt;li&gt;One-time declaration/definition of functions.  In C or C++, you have to
declare your stuff in a header file, then define it in an implementation
file.  Your header file then gets compiled over and over again by everyone
who uses your functions.  (In C++ it gets even worse: your templates have to
be &lt;i&gt;defined&lt;/i&gt; in the header, so compiling every file ends up compiling
half of your bloody program.) This is awful, and is the primary reason
compiling C and C++ is slow.  The problem has also been completely solved
since the 1990's.  Check out Turbo Pascal sometime.  C# and Java, for all
their flaws, have also thoroughly solved this.  (&lt;b&gt;Update 2010/07/21:&lt;/b&gt;
Just because you &lt;i&gt;absolutely must not remove&lt;/i&gt; the preprocessor doesn't
mean you have to &lt;i&gt;use&lt;/i&gt; it for declaring functions.  The preprocessor is
valuable for macros, not for function declarations.)
&lt;p&gt;
&lt;li&gt;Standardized string handling.  Actually I don't think this is very
important; much more important is the ability to keep letting people define
their own string types.  As I mentioned in my previous article, I disagree
with the conventional wisdom that allowing user-defined string types was a
major mistake of C++.  Strings are often the slowest part of your program.
Making them possible to optimize or replace is a good idea; adding some
sugar to construct compile-time string literals directly in a user-defined
data type would be even better.  However, even so, having a decent default
string type couldn't possibly make things worse (as long as you can ignore
it when it gets in the way, ie.  in a kernel).
&lt;p&gt;
&lt;li&gt;Implicit pass-by-reference.  I'm totally addicted to the way python
passes objects by reference, and only by reference.  (Pedants would say it
actually &quot;passes references by value.&quot; I know the difference.  I don't
care.) This is probably hard to pull off without garbage collection support,
but if you can do it, you'll be my hero.  At the very least, let us use
reference syntax wherever we might normally use pointer syntax, because
requiring us to manually dereference pointers all the time was a mistake. 
And once you've done that, maybe remove pointer syntax altogether, because
it's kind of redundant in C++ to have both.  (The only exception is that in
C++, you can't reassign what a reference points to.  But that's only because
they're idiots.  Just &lt;i&gt;let me do that&lt;/i&gt;, and pointer syntax is entirely
obsolete.)
&lt;p&gt;
&lt;li&gt;Typesafe varargs.  C++ totally failed at this, with utterly awful
results (ie. lots and lots of templates that define every version of a
function with 1 to n parameters).  C varargs are great, but they're not
typesafe, and while that's great sometimes, it's less great other times.  A
simple varargs syntax that coerces all the arguments into a particular type
(presumably using your implicit user-defined typecasts from above) would be
easy and highly useful.
&lt;p&gt;
&lt;li&gt;Lots of other things.  This is not a complete list of features you
should add to your language.  Go crazy!  Language design is an act of
creativity, and &lt;i&gt;most language features will not make your language
unacceptable as a C replacement&lt;/i&gt;.  Just don't break any of the &quot;must not
do&quot; rules up above.
&lt;/ol&gt;
&lt;p&gt;
&lt;b&gt;Current C and C++ alternatives and why they aren't popular&lt;/b&gt;
&lt;p&gt;
Apple/NeXT have been single-handledly pushing Objective C since, I don't
know, maybe the 1980's or at least the 90's.  It makes none of the &quot;must not
do&quot; errors (since its dynamically-typed objects are optional).  I personally
suspect the reasons for its slow adoption are simple: a) Objective C isn't
enough better than C and adds nothing if you &lt;i&gt;don't&lt;/i&gt; use its dynamic
typing; and b) the syntax is infernally ugly.  Think about this: for all we
know, the Linux kernel is actually written using every feature in the
kernel-compatible subset of Objective C.  Basically it neither wins nor
loses.  Mu.
&lt;p&gt;
The D language started out as a good idea, but they went crazy in version 2. 
Also, they require garbage collection, so they're instantly disqualified.
&lt;p&gt;
Google Go has tons of great stuff inside and meets almost all of the above
requirements.  Unfortunately it is also garbage collected, so it's instantly
disqualified.  (This one hurts me to the bottom of my soul, because the
other stuff looks so great.  But I'm not disqualifying it because I'm
subjective, I'm disqualifying it because it &lt;i&gt;just won't do the job&lt;/i&gt; as
long as it requires garbage collection.)
&lt;p&gt;
C# is a rather nice language overall and, in fact, has very little in it
that prevents it from being natively compiled.  (Mono actually has a way to
compile it natively nowadays, called their &quot;AOT&quot; (ahead of time) compiler.)
However, it requires a big huge gunky runtime and garbage collection and at
least one system thread and it parses XML at startup time - strace it and
see! - so no luck.  (I
left XML out of the &quot;must not do&quot; list because I thought it was obvious. 
Don't make me regret it.)
&lt;p&gt;
Java actually fails at every single point in this article.  Okay, not
really.  But they did manage to botch most of it in rather spectacular ways.
&lt;p&gt;
Any others that I've missed?
&lt;p&gt;
Note that C++ meets all the above requirements.  That's why it was able to
replace C for so many things.  The main reason C++ doesn't replace C for a
bunch of other things is that it's &lt;i&gt;just too crazy&lt;/i&gt; and it encourages
you, as the developer, to also be crazy.  See my previous rant for all about
that.
&lt;p&gt;
P.S. No, I am not planning to make my own C replacement language.  When
python isn't appropriate, I will continue using and complaining about C++,
while desperately attempting to use it tastefully, if that is even possible.
I will, however, switch to your language if it meets all my requirements. 
So you'll have at least one user.
&lt;p&gt;
&lt;b&gt;Update 2010/07/21:&lt;/b&gt; Wow, this hit the front page of &lt;a
href=&quot;http://news.ycombinator.org/item?id=1536946&quot;&gt;news.ycombinator.com&lt;/a&gt;
in less than 10 minutes.  Thanks, guys.  But I see there is some confusion
about where I stand on C vs. C++ specifically, and why C++ is not the answer
if my question is how to replace C.  Good question!
&lt;p&gt;
The problem with C is that it works but is missing stuff; the problem with
C++ is that it tried to add stuff, but the result is hideous.  That's a
totally subjective evaluation of C++ (see my &lt;a
href=&quot;http://apenwarr.ca/log/?m=201007#18&quot;&gt;previous rant&lt;/a&gt; for some
concrete examples) but it's one that a lot of people seem to agree with. 
The goal here is to identify the &quot;necessary but not sufficient&quot; rules for
creating a C replacement that has a chance of winning.  You may hate C++,
but it met those criteria, and so it became massively popular, hideous or
not.  I just want more options; please make me a language that is necessary,
sufficient, and &lt;i&gt;not hideous&lt;/i&gt;.
&lt;p&gt;
&lt;b&gt;Update 2010/07/22:&lt;/b&gt; People are taking issue with the swearing - and my
love of the C preprocessor - in point #2 above.  I rephrased it slightly but
I'm not removing the swearing.  I almost never swear.  But this time it
matters: removing the preprocessor is treated as a moral issue, but it's
&lt;i&gt;also the reason your language design will never replace C&lt;/i&gt;, and as a
moralizing language designer, you need to know that and make a conscious
decision about it.  Yes, the C preprocessor is used for all sorts of
egregious hacks.  I have bad news for you: &lt;i&gt;that's what it's made for&lt;/i&gt;. 
A language that prevents me from making egregious hacks is a language that
will, eventually, prevent me from doing my job.  Egregious hacks can be used
to create portability where there was none; functions where there were none;
typedefs where there were none (I'm looking at you, C#).  It lets you
transparently replace a call to one function with a call to another.  It
lets you do &quot;#define private public&quot; (one of my favourite C++ tricks) when
the maintainer of a library turns out to be an idiot.  Yeah, you don't want
your language to &lt;i&gt;depend&lt;/i&gt; on these hacks in order to let you write a
good program; C fails here, C++ fails worse.  You want to keep these hacks
to a minimum in production code.  But if you think all production code
should have zero hacks, you are an idealist, and your language design will
never win in the niche where C and C++ win.  (There is most certainly a
niche for languages without hacks.  That's not what this article is about.)
      </description>
    </item>
    <item>
      <title>You can't make C++ not ugly, but you can't not try</title>
      <pubDate>Tue, 20 Jul 2010 03:56:30 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201007#18</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201007#18</guid>
      <description>&lt;p&gt;
...everything that's wrong with C++ comes down to that.
&lt;p&gt;
Background: I've been programming in C++ since about 1993; that's 17 years
now.  As late as 2009, I chose C++ to write our Windows client for &lt;a
href=&quot;http://eqldata.com/&quot;&gt;EQL Data&lt;/a&gt;.  If I were to make that decision
today, I would still choose C++, because, quite simply, nothing else would
work.  (Okay, C would work, but it would be at least 5x as much effort.  So
no thanks.  And for making plugins to legacy Windows apps, there's just
&lt;i&gt;nothing else out there&lt;/i&gt;.)
&lt;p&gt;
So, okay, I know a fair bit about C++.  I've managed 30-person development
teams building huge stuff in C++.  Successfully.  I have some context here.
&lt;p&gt;
And my context is: even if there's nothing better for the job, the truth is
that C++ is incredibly ugly and misdesigned.  C++ is a trap: they
&lt;i&gt;tell&lt;/i&gt; you that you can do anything you want in C++.  Anything!  C++
isn't a language, they say, it's a language construction kit!  Build the
language of your dreams in C++!  And it'll be portable and scalable and fast
and standardized!
&lt;p&gt;
And this is &lt;i&gt;so close to true&lt;/i&gt; that even after using it for 17 years, I
still &lt;i&gt;almost&lt;/i&gt; believe it.  I used to &lt;i&gt;actually&lt;/i&gt; believe it.  But
see, some recent experience with the &quot;amazing innovations&quot; in other
programming languages have convinced me otherwise.
&lt;p&gt;
First of all, if you haven't done much C++, you need to realize: most of the
stuff in there is utter putrid boneheaded crap.  This includes the RTTI and
exceptions stuff; C++'s versions of those were enough to convince a whole
generation of programmers that introspection and exceptions were outright
evil and should be avoided.  But as it turns out, that's only true in C++.
&lt;p&gt;
If you've heard anything about C++, you've probably heard that there's no
standard string class and everybody rolls their own.  That's not actually
one of the bad things, in my opinion.  As a person who's done a lot of
coding in C++, I've actually come to understand that there really &lt;i&gt;are&lt;/i&gt;
good reasons to use different string objects at different times.  In python,
my current language of choice whenever it's appropriate, there's only one
string class, and it's &lt;i&gt;mostly&lt;/i&gt; okay, but every now and then you really
want to just replace one character in the string with one other character
(an O(1) operation) but you can't, so you instead construct a new string (an
O(n) operation) and your program is vastly slower and less scalable. 
(Happily, python makes it pretty easy to create string-&lt;i&gt;like&lt;/i&gt; objects,
particularly using C extensions, so if you really need it, you can make it
still go fast.  But effectively thats just exactly creating your own string
class, like so many people do in C++.  See?  Not always evil.)
&lt;p&gt;
The problem isn't interchangeable string classes.  The problem is that the
&lt;i&gt;default C++ string class is so utterly godawfully stupid&lt;/i&gt;.  No garbage
collection?  Check.  No refcounting?  Check.  Need to allocate/free heap
space just to pass a string constant to a function?  Check.  No support for
null strings?  Check.  Horrendous mess of templates that makes tracing in a
debugger utterly painful?  Check.  Horrendous mess of templates that makes
non-ultramodern compilers unable to optimize them so that, for years, your
toy homemade string class was 5x faster?  Check.  Totally unclear what
character type it uses (actually you can use whatever you want at different
times)?  Check.  Totally missing a sprintf-like formatter so you have to use
something, anything, oh god please save me from iostreams just to produce a
dynamic string?  Check.  Can't append to a string without allocating a whole
new one?  Check.  Using the &quot;+&quot; append operator produces more temporary
objects than you can count?  Check.  Using the &quot;+&quot; operator with two string
constants gives a weird compiler error about adding pointers?  Check.
&lt;p&gt;
In contrast, let's take, say, python's strings: refcounted, passed by
reference, nullable, compatible with string constants, no templates,
trivially easy debugging, always the same character type (although they
changed it in python 3, sigh), include a sprintf-like operator, the + append
operator works fine and multiple appended constants can be optimized at
compile time (python's interpreter compiles to a metalanguage and can do
basic optimizations like this).  They even have an optimized non-constant
append operator in newer versions of python that's more efficient than
making a whole new copy every time.
&lt;p&gt;
How many of these string features required us to use an interpreted
language?  Precisely zero.  An imaginary, fictional version of C++
&lt;i&gt;could&lt;/i&gt; have had a string class with all these features and been just
as fast and efficient.  And I bet a lot fewer people would have written
their own if that had been the case.  There's actually no excuse for the
crap that is C++ std::strings; they aren't better.  They're just, somehow,
the standard.
&lt;p&gt;
Another C++ problem that's close to my heart is function pointers.  Not even
lambdas or anonymous functions - let's not get all fancy, here.  Just plain
pointers to existing named functions.  C++, being a superset of C, has
function pointers, of course.  And while the syntax for them has always been
a little funny, they actually work fine and don't make you want to kill
people too often.  (Everywhere C function pointers are used they should
always have a void *userdata parameter, and when people don't do that (like
in qsort()), then you &lt;i&gt;do&lt;/i&gt; want to kill things...  but that's not C's
fault, and sensible programmers can avoid that mistake.) So ok.  C++ has
function pointers.
&lt;p&gt;
But here's the thing: they utterly failed to extend this concept to include
pointers to methods of an object.
&lt;p&gt;
Okay, that's not really true.  In fact, it's a little-known fact that C++ -
the language, not the insane libraries or templates - has &lt;a
href=&quot;http://www.goingware.com/tips/member-pointers.html&quot;&gt;built-in support
for function pointers that call member functions&lt;/a&gt;.
&lt;p&gt;
The bad news is, this feature is so horrendously ill-conceived that
absolutely nobody uses it for anything.  Seriously.  Nobody.  I tried my
best.  The feature really is actually useless.  The article I linked to
tried desperately to make them look like maybe they have a purpose, but no. 
They just don't.  (You can see the main problem in the linked article under
the section &quot;Member Function Pointers Are Not Just Simple Addresses.&quot; You
might think, oh, of course not.  They're a &quot;this&quot; pointer plus an address,
right?  Ha ha!  Ha ha ha ha!!  No they're not!  They don't &lt;i&gt;have&lt;/i&gt; a
this pointer!  You still have to provide your own this pointer when you call
it!  But it &lt;i&gt;does&lt;/i&gt; store all kinds of crazy other stuff instead so it
can do call-time vtable lookups on multiply-inherited objects!  Ha ha!)
&lt;p&gt;
Utterly useless.  But the bad thing isn't so much that it's useless -
although maybe someone should have noticed that and killed the feature
before it somehow passed the standards committee.  The bad thing is that
there is an obvious way to do it that &lt;i&gt;wouldn't&lt;/i&gt; have been useless:
just make a member function pointer be a struct { obj, funcaddress }. 
Everybody knows that calling a member function obj.f(x,y,z) in C++ is
actually done by calling f(obj,x,y,z).  There would be nothing to it.  Since
you know 'this' at the time you create the function pointer, you can resolve
the funcaddress from the name 'f' at that point - the same way you would
when making any method call, including vtables, multiple inheritance, and
everything - and the code receiving the pointer would always just run
it as (*funcaddress)(obj, ...).  So easy.  Nothing to it.  So very much
terrible C++ code would never have been written if this feature existed.
&lt;p&gt;
But it doesn't.  There are alternatives, of course - numerous ones, and all
terrible, and all incompatible, because the language designers simply failed
utterly to do their job.  The boost (now TR1) one has the cutest syntax, but
God help you if you make a typo using it, because you'll get pages of
template gibberish.
&lt;p&gt;
Stop and think about that for a second.  Template gibberish.  For a simple
&lt;i&gt;function pointer&lt;/i&gt;!  Every language not designed by idiots in the last
20 years, including Turbo Pascal, has some kind of function pointers.  ASM
has function pointers.  C has function pointers.  This isn't hard.  It has
nothing to do with making fancy type-independent efficient data structures,
for which templates/generics are actually justified.  It has to do with a
trivial operation that's a basic part of every compiled language: pushing
some parameters on the stack and jumping to an address.
&lt;p&gt;
While I'm here, no, strings are not &quot;generic&quot; data structures either.  The
fact that std::string is a template is also incredibly insulting.
&lt;p&gt;
Okay, one more example of C++ terribleness.  This one is actually a tricky
one, so I can almost forgive the C++ guys for not thinking up the &quot;right&quot;
solution.  But it came up again for me the other day, so I'll rant about it
too: dictionary item assignment.
&lt;p&gt;
What happens when you have, say, a std::map of std::string and you do
&lt;tt&gt;m[5] = &quot;chicken&quot;&lt;/tt&gt;?  Moreover, what happens if there &lt;i&gt;is&lt;/i&gt; no
m[5] and you do &lt;tt&gt;std::string x = m[5]&lt;/tt&gt;?
&lt;p&gt;
Answer: m[5] &quot;autovivifies&quot; a new, empty string and stores it in location 5. 
Then it returns a reference to that location, which in the first example,
you reassign using std::string::operator=.  In the second example, the
autovivified string is copied to x - and left happily floating around,
empty, in m[5].
&lt;p&gt;
Ha ha!  In what universe are these semantics reasonable?  In what rational
set of rules does the &lt;i&gt;right-hand-side of an assignment statement get
modified by default?&lt;/i&gt; Maybe I'm crazy - no, that's not it - but when I
write m[5] and there's no m[5], I think there are only two things that are
okay to happen.  Either m[5] returns NULL (a passive indicator that there is
no m[5], like you'd expect from C) or m[5] throws an exception (an
aggressive indicator that there is no m[5], like you'd see in python).
&lt;p&gt;
Ah, you say.  But look!  If that happened, then the first statement - the
one assigning to m[5] - wouldn't work!  It would crash because you end up
assigning to NULL!
&lt;p&gt;
Yes.  Yes it would.  In C++ it would, because the people who designed C++
are idiots.
&lt;p&gt;
But in python, it works perfectly (even for user-defined types).  How? 
Simple. Python's parser has a little hack in it - which I'm sure must hurt
the python people down to the cores of their souls, so much do they hate
hacks - that makes m[5]= parse differently than just plain m[5].
&lt;p&gt;
The python parser converts o[x]=y directly into o.__setitem__(x,y).  Whereas
o[x] without a trailing equal sign converts directly into o.__getitem__(x). 
It's very sad that the parser has to do such utterly different things with
two identical-looking uses of the square bracket operator.  But the result
is you get what you expect: __getitem__ throws an exception if there's no
m[5].  __setitem__ doesn't.  __setitem__ puts stuff &lt;i&gt;into&lt;/i&gt; your object;
it doesn't waste time pulling stuff &lt;i&gt;out of&lt;/i&gt; your object (unless that's
a necessary internal detail for your data structure implementation).
&lt;p&gt;
But even that isn't the worst thing.  Here's what's worse: C++'s crazy
autovivification stuff makes it &lt;i&gt;slower&lt;/i&gt;, because you have to construct
an object just so you can throw it away and reassign it.  Ha ha!  The crazy
language where supposedly performance is all-important actually assigns to
maps &lt;i&gt;slower&lt;/i&gt; than python can!  All in the name of having language
purity, so we don't have to have stupid parser hacks to make [] behave two
different ways!
&lt;p&gt;
...
&lt;p&gt;
&quot;...Well,&quot; said the C++ people.  &quot;Well.  We can't have that.&quot;
&lt;p&gt;
So here's what they invented.  Instead of inventing a sensible new []=
operator, they went even more crazy.  They redefined things such that, if
your optimizer is sufficiently smart, it can make all the extra crap go
away.
&lt;p&gt;
There's something in C++ called the &quot;&lt;a
href=&quot;http://en.wikipedia.org/wiki/Return_value_optimization&quot;&gt;return value
optimization&lt;/a&gt;.&quot; Normally, if you do something like &quot;MyObj x = f()&quot;, and f
returns a MyObj, then what would need to happen is that 'x' gets constructed
using the default constructor, then f() constructs a new object and returns
it, and then we call x.operator= to copy the object from f()'s return value,
then we destroy f()'s return value.
&lt;p&gt;
As you might imagine, when implementing the [] setter on a map, this would
be kind of inefficient.
&lt;p&gt;
But because the C++ people so desperately wanted this sort of thing to be
fast, they allowed the compiler to optimize out the creation of x and the
copy operation; instead, they just tell f() to construct its return value
right into x.  If you think about it hard enough, you can see that, assuming
the stars all align perfectly, &lt;tt&gt;m[5] = &quot;foo&quot;&lt;/tt&gt; can benefit from this
operation.  Probably only if m.operator[] is inlined, but of course it is -
it's a template!  Everything in a template is inlined!  Ha ha!
&lt;p&gt;
So actually C++ maps are as fast as python maps, assuming your compiler
writers are amazingly great, and a) implement the (optional) return-value
optimization; b) inline the right stuff; and c) don't screw up their
overcomplicated optimizer so that it makes your code randomly not work in
other places.
&lt;p&gt;
Okay, cool, right?  Isn't this a triumph of engineering - an amazingly world
class optimizer plus an amazingly supercomplex specification that allows
just the right combination of craziness to get what you want?
&lt;p&gt;
NO!
&lt;p&gt;
No it is not!
&lt;p&gt;
It is an absolute failure of engineering!  Do you want to know what real
engineering is?  It's this:
&lt;p&gt;
&lt;tt&gt;map_set(m, 5, &quot;foo&quot;);&lt;/tt&gt;&lt;br&gt;
&lt;tt&gt;char *x = map_get(m, 5);&lt;/tt&gt;
&lt;p&gt;
That plain C code runs exactly as fast as the above hyperoptimized
ultracomplex C++.  &lt;i&gt;*And*&lt;/i&gt; it returns NULL when m[5] doesn't exist,
which C++ fails to do.
&lt;p&gt;
In the heat of the moment, it's easy to lose sight of just how much of C++
is absolutely senseless wankery.
&lt;p&gt;
And this, my friends, is the problem.
&lt;p&gt;
As with any bureaucracy, the focus slowly shifts from finding a simple,
elegant way to solve your problem to &lt;i&gt;just goddamn winning this one battle
with the system so that you can get the bloody thing working at all&lt;/i&gt;.  It
would have been easy, at any time, for the C++ committee to have just added
a new operator[]=.  It would have been totally backward-compatible: any
object without an operator[]= would keep working just like it always has.
&lt;p&gt;
But they couldn't do that.  Doing that would be admitting defeat.
&lt;p&gt;
They could have made up a new syntax for sensible member function pointers,
any time they wanted.  Again, no concern about backwards compatibility - if
you don't use it, it doesn't affect you.
&lt;p&gt;
They could have written a sensible string class.  In fact, people did.  Lots
of people!  But for some reason, they standardized on the non-sensible one.
Now C++ users are forever cursed: either you use std::string, and pay
endlessly for its suck, or you use your own string class, and be one of
those people who constantly gets criticized for designing their own string
class.
&lt;p&gt;
It is possible to write C++ that's not crap - in theory.  This is because
it's possible to write C that's not crap, and C programs will compile as
C++.  Then, you can add a sprinkle of the non-sucky parts of C++ -
deterministic construction/destruction (RAII) is one of them - and you'll
have a program that's undoubtedly better, more readable, and easier to debug
than it would have been in pure C.
&lt;p&gt;
But you can't stop there.  You should, but you can't.  Nobody can.  It would
be superhuman.  Because you'll see something that &lt;i&gt;should&lt;/i&gt; be a little
clearer, a little easier.  Maybe it's string concatenation, maybe it's
member function pointers, maybe it's operator[].  But you'll see it, and
you'll start trying to solve it.  And 1000 lines of code later, you'll have
made your life - and the lives of everyone who has to maintain your
programs - much worse.
&lt;p&gt;
For me it was function pointers.  Over the years in &lt;a
href=&quot;http://github.com/apenwarr/wvstreams/&quot;&gt;wvstreams&lt;/a&gt;, I tried doing
them so many different ways - using C-style function pointers with wrapper
functions, using inheritance and virtual functions, using the insane C++
member function pointers, using templates &lt;i&gt;and&lt;/i&gt; the insane C++ member
function pointers.  Finally, nowadays, function pointers in WvStreams use
boost's new functor stuff, which has been standardized by TR1.  And every
single time I use one, I have to look up the syntax.
&lt;p&gt;
For my own library that I've spent the last 12 years building.  I have to
&lt;i&gt;look up the syntax to declare a callback&lt;/i&gt;.
&lt;p&gt;
I should have just stuck with plain C function pointers.
&lt;p&gt;
Let this be a warning to you.
      </description>
    </item>
    <item>
      <title>A Programmer's Code of Ethics</title>
      <pubDate>Sun, 23 May 2010 19:45:28 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#22</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#22</guid>
      <description>&lt;p&gt;
&lt;ol&gt;&lt;li&gt;My programs encode the rules of modern society.  I will take full
responsibility for the programs I write.
&lt;p&gt;
&lt;li&gt;I will not write a program that intentionally fails to operate.
&lt;p&gt;
&lt;li&gt;I will not write a program that refuses to do tomorrow what
it was able to do yesterday.
&lt;p&gt;
&lt;li&gt;I will not create a single point of failure, whether technical or
political.
&lt;p&gt;
&lt;li&gt;I will not encode foolish rules just because someone paid me to do it.
&lt;p&gt;
&lt;li&gt;I will not give people what they want if what they want is not good enough.
&lt;p&gt;
&lt;li&gt;I will not stop people from taking my program's ideas and making them
better.
&lt;p&gt;
&lt;li&gt;I will write programs to help each person produce their best, not to help
the masses produce mediocrity.
&lt;p&gt;
&lt;li&gt;I will correct those who believe my program's failure is anyone's
fault but mine.
&lt;p&gt;
&lt;li&gt;I will write programs to benefit even the people who don't deserve it.
&lt;/ol&gt;
&lt;p&gt;
&amp;nbsp;
&lt;p&gt;
&lt;b&gt;Condensed &quot;New Testament&quot; Version&lt;/b&gt;
&lt;p&gt;
&lt;ul&gt;Don't write for others a program you wouldn't want written for
you.&lt;/ul&gt;
&lt;p&gt;
&amp;nbsp;
&lt;p&gt;
&lt;b&gt;Commentary&lt;/b&gt;
&lt;p&gt;
Do I always follow all the above rules perfectly?  Certainly not.  In fact,
I think I've broken every single one of them.
&lt;p&gt;
But thinking over all those situations and knowing what I know now, I'm
pretty sure that in every case, it would have been better if I'd done the
right thing.  The exceptions don't feel like the right move; they just feel
dirty.
&lt;p&gt;
That's how I know I'm on the right track.
&lt;p&gt;
&lt;b&gt;Update 2010/05/22:&lt;/b&gt; Based on a suggestion from Chris Frey, slightly
rephrased point #3.
      </description>
    </item>
    <item>
      <title>At last, the circle is complete</title>
      <pubDate>Wed, 19 May 2010 16:33:18 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#20</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#20</guid>
      <description>&lt;p&gt;
My twitter search RSS feed (yes, &lt;a
href=&quot;http://apenwarr.ca/log/?m=200912#24&quot;&gt;I have one&lt;/a&gt;, so shoot me) for
&quot;apenwarr&quot; returned a hit today in which the only usage of the word
&quot;apenwarr&quot; was an URL hidden behind a bit.ly link.
&lt;p&gt;
Oh yes.  That means twitter search is now decoding bit.ly URLs as part of
the indexing process, but of course it *still* serves you the original
stupid bit.ly links.
&lt;p&gt;
Thank you, oh great technology gods, for inventing new uses for excess CPU
that I never could have imagined.
&lt;p&gt;
In other news, SEOs can now increase the keyword relevance of their twitter
links; just have bit.ly resolve to something like
&lt;tt&gt;http://whatever.com/stuff?magic-keywords=fuzzy-wuzzy-chickens-multiplied-by-gargantuan-apple-google-flash-ipad-porn-naked&lt;/tt&gt;
      </description>
    </item>
    <item>
      <title>Tell me what surprised you: iPad Edition</title>
      <pubDate>Tue, 18 May 2010 23:31:35 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#18</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#18</guid>
      <description>&lt;p&gt;
If someone is about to tell you a long story about a trip they were on, you
should make just one request: &quot;Tell me what surprised you.&quot; That simple
query changes the whole nature of the conversation.
&lt;p&gt;
For example, we all know the basic stuff about Paris.  It has French people. 
The food is good.  It's pretty.  But what &lt;i&gt;surprised&lt;/i&gt; you about
Paris?  Now there's something we can talk about.&lt;sup&gt;1&lt;/sup&gt;
&lt;p&gt;
So. Yes, I got an iPad.  And I'll do you a favour: I'll tell you 
my surprise.
&lt;p&gt;
What surprised me was iBooks.
&lt;p&gt;
No, no, iBooks looks and works exactly like in the pictures and ads.  It
really is just like that, for better and for worse.  That's not the
surprise.
&lt;p&gt;
The surprise was that it wasn't installed by default.
&lt;p&gt;
Think about that.  I had to go to the app store, painfully convince it I was
a U.S. resident, search for &quot;iBooks&quot; (&quot;books&quot; is definitely not good
enough), and download it, all just to get started.
&lt;p&gt;
Meanwhile, I downloaded a bunch of other apps.  Some of them had ads.  Many
of those ads were for the Amazon Kindle app, which is also in the app store,
and also free, and doesn't require me to be American.  And I could click on
any of those ads and get straight to app store.  Two more taps, and I'm
done.
&lt;p&gt;
There weren't any ads for the iBooks app.  Anywhere.  Thus it was
&lt;i&gt;harder&lt;/i&gt; to find out about iBooks, and as hard or harder to download
it, than the Kindle app.
&lt;p&gt;
I've been in the computer world for a long time.  I've observed Microsoft
and how they do things.  Heck, I've observed &lt;i&gt;Apple&lt;/i&gt; and how they do
things.  And one thing I've seen for sure: bundling and cross-selling
&lt;i&gt;work&lt;/i&gt;.  If this were Microsoft, they wouldn't have hesitated for a
second to give iBooks a boost by including it with the OS.
&lt;p&gt;
But Apple &lt;i&gt;deliberately left it out&lt;/i&gt;.  iBooks has to compete with
Kindle in the very same app store, with no free publicity (other than being
a &quot;featured&quot; app in some iPad ads and PR).
&lt;p&gt;
I can imagine the iBooks team being told that this is it, yes, you can do
your bookstore however you want, but we're not going to make it any easier
on you.  You have to be the best bookstore in the world all by yourself,
not just because you tagged along with something that was already great
without you.
&lt;p&gt;
Now &lt;i&gt;that&lt;/i&gt; is surprising.
&lt;p&gt;
For the record, iBooks is doing pretty well so far: it absolutely beats the
snot out of Kindle for the iPhone/iPad in pretty much every way (except book
prices, which are much higher than Amazon's).&lt;sup&gt;2&lt;/sup&gt;
&lt;p&gt;
Also interesting to consider is why they allowed this competition with
books, but not with music, movies, and phone calls.  Have they had a change
of heart?  A secret contractual obligation?  Does Steve Jobs really just not
care about books, as he previously claimed?
&lt;p&gt;
You might also ask why their Pages, Numbers, and Presentations (or whatever
it's called) apps aren't bundled or cross-sold either; anybody making a word
processor is on equal footing with Apple's iWork team.  And there's no
Weather, Stocks, Voice Memos, Clock, or Calculator app included on an iPad
either, even though they were all on the iPhone.  The iPad has &lt;i&gt;less&lt;/i&gt;
bundled stuff than ever before - the diametric opposite of what Microsoft
has done in any version of Windows, ever.
&lt;p&gt;
The rest of the iPad?  It's pretty much as expected.  I'll spare you.
&lt;p&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;p&gt;
&lt;sup&gt;1&lt;/sup&gt; What surprised me about Paris was that, at their fruit stands,
every fruit is arranged with absolute care and precision.  Compare to a
typical grocery store in Canada, where fruit is typically dumped into a bin
so you can sort through it yourself.  When I think about &lt;i&gt;how much more
time&lt;/i&gt; it must take to do it the hard way, yes, it surprises me.  How can
they afford to &lt;i&gt;do&lt;/i&gt; that?  It's magic.  (I also had other &lt;a
href=&quot;http://apenwarr.ca/log/?m=200704#21&quot;&gt;related observations&lt;/a&gt; at the
time.)
&lt;p&gt;
&lt;sup&gt;2&lt;/sup&gt; I won't bother describing the Kindle app's failings in detail. 
To get you started, I have just two words for you: &lt;i&gt;page numbers&lt;/i&gt;. 
Compare them in Kindle vs. iBooks.  Someone at Amazon needs to be shot.
&lt;p&gt;
&lt;b&gt;Update 2010/05/18:&lt;/b&gt; Hmm, &lt;a href=&quot;http://jordanlev.com/&quot;&gt;jordanlev&lt;/a&gt;
wrote to tell me that on his iPad, it popped up a message right away asking
whether he wanted to download iBooks.  So maybe they're not playing all that
nice after all.  He also linked to an &lt;a
href=&quot;http://www.antipope.org/charlie/blog-static/2010/05/cmap-9-ebooks.html&quot;&gt;interesting
article about the ebook market by Charlie Stross&lt;/a&gt;.
      </description>
    </item>
    <item>
      <title>Mailing lists are cheap...</title>
      <pubDate>Tue, 11 May 2010 20:06:03 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#11</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#11</guid>
      <description>&lt;p&gt;
...but I still didn't think I'd bother with one for &lt;a
href=&quot;http://github.com/apenwarr/sshuttle&quot;&gt;sshuttle&lt;/a&gt;, which was
just intended to be a weekend toy project.  Seems people are actually using
it, though, and it's picked up quite a few github followers already.  (62
followers isn't &lt;i&gt;that&lt;/i&gt; much, but the thing is only 10 days old.)
&lt;p&gt;
So okay, here you go: &lt;a
href=&quot;http://groups.google.com/group/sshuttle&quot;&gt;the sshuttle mailing
list&lt;/a&gt;.
&lt;p&gt;
By the way, it seems to not be common knowledge that you can subscribe to
googlegroups mailing lists without having a Google account or ever
using their web interface.  The secret is to send an email to
&quot;&lt;b&gt;groupname&lt;/b&gt;+subscribe@googlegroups.com&quot;, where groupname is the name
of the group, in this case, &lt;b&gt;sshuttle&lt;/b&gt;.  Note that plus sign.  It's not
a minus sign.
      </description>
    </item>
    <item>
      <title>sshuttle 0.30: automatic route and hostname discovery</title>
      <pubDate>Sat, 08 May 2010 19:56:28 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#10</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#10</guid>
      <description>&lt;p&gt;
My fancypants new &lt;a href=&quot;http://github.com/apenwarr/sshuttle/&quot;&gt;sshuttle
transproxy VPN&lt;/a&gt; could already work even if all you had was a ssh session
to the other side.  And it avoided the TCP-over-TCP trap.  And sure, I even
made it &lt;a href=&quot;http://apenwarr.ca/log/?m=201005#05&quot;&gt;upload itself&lt;/a&gt; to
the other end automatically so you wouldn't have to.  And it apparently
works on MacOS clients now, &lt;a
href=&quot;http://serverfault.com/questions/138622/transparent-proxying-leaves-sockets-with-syn-rcvd-in-macos-x-10-6-snow-leopard-a&quot;&gt;except
Snow Leopard which is not-so-shockingly buggy&lt;/a&gt;, and maybe even on
FreeBSD.  And it manages latency, even under heavy use, so performance
doesn't start sucking when you transfer a big file.
&lt;p&gt;
So in all those ways, it was already much better than the old Tunnel Vision,
which among other things, you had to install by hand on both ends of the
connection, and after that the performance was a bit random.
&lt;p&gt;
But Tunnel Vision still had a few tricks that sshuttle missed.  The first
one is automatic route guessing.  When TV connected to the other end, the
server would tell the client what subnets it was able to reach, and then the
client would automatically set up routes for those subnets to go through the
tunnel.  Neat, right?  But with sshuttle, you had to tell the client what to
route by hand.  No more:
&lt;p&gt;
&lt;pre&gt;     sshuttle -N -r username@servername&lt;/pre&gt;
&lt;p&gt;
The new -N option enables automatic network determination.  You can still
add additional subnets (like 0/0 for people who want to route &quot;everything&quot;)
if you want.
&lt;p&gt;
Another fun feature of Tunnel Vision was automatic hostname mapping.  You
know what sucks about connecting to a remote VPN?  You probably don't, so
I'll tell you.  What sucks is DNS.  Your local DNS server doesn't know
anything about the hostnames on the other end, and of course they're private
so they're not in the public DNS either.  So when you try &quot;ssh
internalserver&quot;, and &quot;internalserver&quot; is some server on the remote internal
network, you get an error.
&lt;p&gt;
This one is a lot trickier to solve.  After all, there's no good way to get
a list of hostnames for you to replicate.  And once you do, there's
also no good way to add them to the local DNS.  But does that stop us? 
Certainly not.  It merely confuses us.
&lt;p&gt;
&lt;pre&gt;     shuttle -H -r username@servername&lt;/pre&gt;
&lt;p&gt;
The new -H option tells the remote sshuttle instance to start prodding
around wherever it can (currently, that means at least the local /etc/hosts
file, samba nameservers and browse masters, and a bit of DNS) to try to find
good hostnames and their matching IP addresses.  As it finds them, it beams
them back to your client, which adds them temporarily to your local
/etc/hosts file.  Gross?  Oh boy, is it ever!  But it works.  More or less.
&lt;p&gt;
It would be kind of neat to have it get browse lists from things like mdns
(aka &quot;zeroconf&quot; aka &quot;bonjour&quot;) but I have no idea how to do that.
&lt;p&gt;
The old Tunnel Vision &lt;i&gt;sort of&lt;/i&gt; had this feature, but it didn't have
sshuttle's amazing Name Prodding Technology(tm).  You had to configure the
names yourself.  As it happened, our proprietary Nitix servers had some very
scary code to automatically track local hostnames and configure Tunnel
Vision appropriately, so the name mapping worked pretty well there.  And
Nitix servers were usually acting as your DNS, so they could set that up
nicely too.  Sadly, Nitix's old name prodding is mostly obsolete due to the
way modern networks are run (mdns, domain controllers, names-by-dhcp,
switched ethernet, and so on).  But life marches on.  And we all still want
the same things.
&lt;p&gt;
Anyway, anybody who knows how to get a good list of hostname/ip pairs out of
mdns, ideally in a portable fashion, send me an email :) You might also want
to look at &lt;a
href=&quot;http://github.com/apenwarr/sshuttle/tree/master/hostwatch.py&quot;&gt;hostwatch.py&lt;/a&gt;
and see if you can think of any other interesting sources to scan for names.
      </description>
    </item>
    <item>
      <title>Gunless</title>
      <pubDate>Sat, 08 May 2010 19:25:40 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#08</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#08</guid>
      <description>&lt;p&gt;
&lt;a href=&quot;http://www.hour.ca/film/film.aspx?iIDArticle=19695&quot;&gt;Movie
recommendation&lt;/a&gt;.  There's not much to say about it that the reviews
haven't already.  But if you're looking for something with a little more
intelligence than a Hollywood Extravaganza, but not so intelligent that it
bores me to tears like most independent films, this one works.
&lt;p&gt;
&lt;ul&gt;&lt;i&gt;The idea that the Wild West of the United States didn't have any law
is completely bogus. There was law. They were settled by laws like we were.
And the idea that we had nothing but law and had no weaponry is also
ludicrous. Of course we did.&lt;/i&gt;&lt;p&gt;-- &lt;a
href=&quot;http://www.thestar.com/entertainment/movies/article/801314--paul-gross-is-gunless-but-not-hairless&quot;
&gt;Paul Gross on the Film's Historical Accuracy&lt;/a&gt;&lt;/ul&gt;
&lt;p&gt;
So it's also useful if you want to learn totally wrong but funny things
about the Canadian &quot;wild west.&quot;
      </description>
    </item>
    <item>
      <title>Uploading yourself for fun and profit (plus: sshuttle 0.20 "almost" works on MacOS)</title>
      <pubDate>Wed, 05 May 2010 22:50:00 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#05</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#05</guid>
      <description>&lt;p&gt;
After trying out the initial version of &lt;a
href=&quot;http://github.com/apenwarr/sshuttle&quot;&gt;sshuttle&lt;/a&gt; that I produced this
weekend, a few people asked me whether it would be possible to make it work
without installing a sshuttle server on the server machine.  Can it work
with *just* an sshd, they wondered?
&lt;p&gt;
Good question.
&lt;p&gt;
Some people pointed out ssh's -D option (dynamic port forwarding using a
SOCKS proxy).  If we just used that (ie. the sshuttle client transproxies
stuff into ssh's SOCKS server), then there wouldn't need to be a server
side for sshuttle, and that would solve the problem.  But sadly, sshd's
latency management is pretty thoroughly awful - among other things, it sets
its SO_SNDBUF way too high - so if you have a few connections going at once,
performance takes a dump.  sshuttle has some clever stuff to make
sure that doesn't happen even if you've got giant ISOs downloading over
your VPN link.  I'd like to keep that.
&lt;p&gt;
So then I said to myself, hey, self, what if we just uploaded our source
code to the remote server and executed it automatically?  It works for
viruses (technically worms), after all.
&lt;p&gt;
You know it's never a good thing when I start talking to myself.  And yet
the result is surprisingly simple and elegant.  Here's a simplified version
of what the &quot;stage 1 reassembler&quot; looks like:
&lt;p&gt;
&lt;pre&gt;
   ssh hostname python -c '
   	import sys;
   	exec compile(sys.stdin.read(%d), &quot;assembler.py&quot;, &quot;exec&quot;)'
&lt;/pre&gt;
&lt;p&gt;
Where &quot;%d&quot; is substituted with the length of assembler.py.  Assembler.py, by
the way, is the &quot;stage 2 reassembler,&quot; which looks like this:
&lt;p&gt;
&lt;pre&gt;
    import sys, zlib
&lt;p&gt;
    z = zlib.decompressobj()
    mainmod = sys.modules[__name__]
    while 1:
        name = sys.stdin.readline().strip()
        if name:
            nbytes = int(sys.stdin.readline())
            if verbosity &gt;= 2:
                sys.stderr.write('remote assembling %r (%d bytes)\n'
                                 % (name, nbytes))
            content = z.decompress(sys.stdin.read(nbytes))
            exec compile(content, name, &quot;exec&quot;)
            # FIXME: this crushes everything into a single module namespace,
            # then makes each of the module names point at this one. Gross.
            assert(name.endswith('.py'))
            modname = name[:-3]
            mainmod.__dict__[modname] = mainmod
        else:
            break
    main()
&lt;/pre&gt;
&lt;p&gt;
Yeah, that's right, I gzipped it.
&lt;p&gt;
You know the best part?  When the server throws an exception, it still gives
the right filenames and line numbers in the backtrace, because we assemble
each file separately.
&lt;p&gt;
If anybody knows the right python incantation to make it import each of the
modules as a separate actual module object (rather than just dumping it all
into the global namespace, as the comment indicates) please send a patch.
&lt;p&gt;
Grab &lt;a href=&quot;http://github.com/apenwarr/sshuttle&quot;&gt;the latest version of
sshuttle VPN on GitHub&lt;/a&gt;.
&lt;p&gt;
&lt;b&gt;&quot;Almost&quot; works on MacOS&lt;/b&gt;
&lt;p&gt;
Responding to popular request, I thought I would try to get the sshuttle
client working on MacOS.  (The sshuttle server already works - or at least
it should work - on just about any platform with an sshd.)
&lt;p&gt;
MacOS, being based on BSD, uses the same ipfw stuff as FreeBSD seems to use. 
So it &quot;should&quot; be just a matter of having it auto-detect whether the current
system uses iptables or ipfw, then run the right commands, right?
&lt;p&gt;
Well, almost.  I did all that stuff, and I've *almost* got the rules
working, but I just can't make it work right.  I'm using MacOS X Snow
Leopard on my laptop.  I checked it in and pushed it anyway in case anybody
wants to take a look; the final fix is probably a one liner.
&lt;p&gt;
For more information on my conundrum, see my (as yet unanswered) &lt;a
href=&quot;http://serverfault.com/questions/138622/transparent-proxying-leaves-sockets-with-syn-rcvd-in-macos-x-10-6-snow-leopard-a&quot;&gt;question
on ServerFault&lt;/a&gt;.  If you can contribute an answer, you'll forever be my
hero.  Even if you don't know anything about ipfw, if you could run through
the steps on your version of MacOS or BSD and tell me what happens, it could
help narrow things down.
&lt;p&gt;
Enjoy!
&lt;p&gt;
&lt;b&gt;Update 2010/05/05:&lt;/b&gt; Thanks to Ed Maste and drheld for helping confirm. 
It seems that FreeBSD and MacOS 10.5 Leopard work fine - which means
sshuttle 0.20 should work for you, yay! - while Snow Leopard consistently
does not.
&lt;p&gt;
Really, that restores a bit of balance to the universe; since
everyone I know who's upgraded to Snow Leopard went through huge pain and
suffering, I was a little shocked to find that my own upgrade had been
harmless, and Erin's really did make her computer go &lt;i&gt;much faster&lt;/i&gt;
(boggle).  Now that Snow Leopard has finally screwed me after all, I once
again feel like things are as they should be.
      </description>
    </item>
    <item>
      <title>sshuttle: a new kind of userspace VPN</title>
      <pubDate>Sun, 02 May 2010 18:57:23 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201005#02</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201005#02</guid>
      <description>&lt;p&gt;
I just spent an afternoon working on a new kind of VPN.  You can get
the first release, &lt;a href=&quot;http://github.com/apenwarr/sshuttle&quot;&gt;sshuttle
0.10, on github&lt;/a&gt;.
&lt;p&gt;
As far as I know, sshuttle is the only program that solves the following
common case:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Your client machine (or router) is Linux.
&lt;/li&gt;
&lt;li&gt;You have access to a remote network via ssh.
&lt;/li&gt;
&lt;li&gt;You don't necessarily have admin access on the remote network.
&lt;/li&gt;
&lt;li&gt;The remote network has no VPN, or only stupid/complex VPN protocols (IPsec, PPTP, etc). Or maybe you &lt;i&gt;are&lt;/i&gt; the admin and you just got frustrated with the awful state of VPN tools.
&lt;/li&gt;
&lt;li&gt;You don't want to create an ssh port forward for every single host/port on the remote network.
&lt;/li&gt;
&lt;li&gt;You hate openssh's port forwarding because it's randomly slow and/or stupid.
&lt;/li&gt;
&lt;li&gt;You can't use openssh's PermitTunnel feature because it's disabled by default on openssh servers; plus it does TCP-over-TCP, which has terrible performance (see below).
&lt;/li&gt;
&lt;/ul&gt;
This is how you use it:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;git clone git://github.com/apenwarr/sshuttle&lt;/tt&gt;&lt;br&gt;on your client and server machines. The server can be any ssh server with python available; the client must be Linux with iptables, and you'll need root or sudo access.
&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;http://apenwarr.ca/log/sshuttle -r username@sshserver 0.0.0.0/0 -vv&lt;/tt&gt;
&lt;/li&gt;
&lt;/ul&gt;
That's it!  Now your local machine can access the remote network as if you
were right there!  And if your &quot;client&quot; machine is a router, everyone on
your local network can make connections to your remote network.
&lt;p&gt;
This creates a transparent proxy server on your local machine for all IP
addresses that match 0.0.0.0/0.  (You can use more specific IP addresses if
you want; use any number of IP addresses or subnets to change which
addresses get proxied.  Using 0.0.0.0/0 proxies &lt;i&gt;everything&lt;/i&gt;, which is
interesting if you don't trust the people on your local network.)
&lt;p&gt;
Any TCP session you initiate to one of the proxied IP addresses will be
captured by sshuttle and sent over an ssh session to the remote copy of
sshuttle, which will then regenerate the connection on that end, and funnel
the data back and forth through ssh.
&lt;p&gt;
Fun, right?  A poor man's instant VPN, and you don't even have to have
admin access on the server.
&lt;p&gt;
&lt;b&gt;Theory of Operation&lt;/b&gt;
&lt;p&gt;
sshuttle is not exactly a VPN, and not exactly port forwarding.  It's kind
of both, and kind of neither.
&lt;p&gt;
It's like a VPN, since it can forward every port on an entire network, not
just ports you specify.  Conveniently, it lets you use the &quot;real&quot; IP
addresses of each host rather than faking port numbers on localhost.
&lt;p&gt;
On the other hand, the way it *works* is more like ssh port forwarding than
a VPN.  Normally, a VPN forwards your data one packet at a time, and
doesn't care about individual connections; ie. it's &quot;stateless&quot; with respect
to the traffic.  sshuttle is the opposite of stateless; it tracks every
single connection.
&lt;p&gt;
You could compare sshuttle to something like the old &lt;a
href=&quot;http://en.wikipedia.org/wiki/Slirp&quot;&gt;Slirp&lt;/a&gt; program, which was a
userspace TCP/IP implementation that did something similar.  But it
operated on a packet-by-packet basis on the client side, reassembling the
packets on the server side.  That worked okay back in the &quot;real live serial
port&quot; days, because serial ports had predictable latency and buffering.
&lt;p&gt;
But you can't safely just forward TCP packets over a TCP session (like ssh),
because TCP's performance depends fundamentally on packet loss; it
&lt;i&gt;must&lt;/i&gt; experience packet loss in order to know when to slow down!  At
the same time, the outer TCP session (ssh, in this case) is a reliable
transport, which means that what you forward through the tunnel &lt;i&gt;never&lt;/i&gt;
experiences packet loss.  The ssh session itself experiences packet loss, of
course, but TCP fixes it up and ssh (and thus you) never know the
difference.  But neither does your inner TCP session, and extremely screwy
performance ensues.
&lt;p&gt;
sshuttle assembles the TCP stream locally, multiplexes it statefully over
an ssh session, and disassembles it back into packets at the other end.  So
it never ends up doing TCP-over-TCP.  It's just data-over-TCP, which is
safe.
&lt;p&gt;
&lt;b&gt;Useless Trivia&lt;/b&gt;
&lt;p&gt;
Back in 1998 (12 years ago!  Yikes!), I released the first version of &lt;a
href=&quot;http://alumnit.ca/wiki/?TunnelVisionReadMe&quot;&gt;Tunnel Vision&lt;/a&gt;, a
semi-intelligent VPN client for Linux.  Unfortunately, I made two big mistakes: 
I implemented the key exchange myself (oops), and I ended up doing
TCP-over-TCP (double oops).  The resulting program worked okay - and people
used it for years - but the performance was always a bit funny.  And nobody
ever found any security flaws in my key exchange, either, but that doesn't
mean anything. :)
&lt;p&gt;
The same year, dcoombs and I also released Fast Forward, a proxy server
supporting transparent proxying.  Among other things, we used it for
automatically splitting traffic across more than one Internet connection (a
tool we called &quot;Double Vision&quot;).
&lt;p&gt;
I was still in university at the time.  A couple years after that, one of my
professors was working with some graduate students on the technology that
would eventually become &lt;a href=&quot;http://www.slipstream.com/&quot;&gt;Slipstream
Internet Acceleration&lt;/a&gt;.  He asked me to do a contract for him to build an
initial prototype of a transparent proxy server for mobile networks.  The
idea was similar to sshuttle: if you reassemble and then disassemble the TCP
packets, you can reduce latency and improve performance vs.  just forwarding
the packets over a plain VPN or mobile network.  (It's unlikely that any of
my code has persisted in the Slipstream product today, but the concept is
still pretty cool.  I'm still horrified that people use plain TCP on
complex mobile networks with crazily variable latency, for which it was
never really intended.)
&lt;p&gt;
That project I did for Slipstream was what first gave me the idea to merge
the concepts of Fast Forward, Double Vision, and Tunnel Vision into a single
program that was the best of all worlds.  And here we are, at last, 10 years
later.  You're welcome.
&lt;p&gt;
&lt;b&gt;Update 2010/05/02:&lt;/b&gt; Oops, maybe it works a little &lt;i&gt;too&lt;/i&gt; well.  If
you're one of the people who was surprised to see &lt;a
href=&quot;http://eqldata.com/&quot;&gt;eqldata.com&lt;/a&gt; where apenwarr.ca should have
been this morning, that's because I left my sshuttle proxy running -
connected to the &quot;real&quot; server on eqldata.com - as a stress test.  Seems
that even my DynDNS provider thought my unreliable home PC was part of the
eqldata.com network :)  (Also, it failed the stress test: some sort of file
descriptor leak after a few hours.  Will fix.)
      </description>
    </item>
    <item>
      <title>Three types of distributed system designers</title>
      <pubDate>Mon, 26 Apr 2010 06:13:39 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201004#24</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201004#24</guid>
      <description>&lt;p&gt;
1. &lt;b&gt;Paranoid privacy nuts.&lt;/b&gt;  Systems designed by these people never
become popular because paranoid people don't have any friends. 
&lt;i&gt;(Examples: ZKS, Freenet, GPG.)&lt;/i&gt;
&lt;p&gt;
2. &lt;b&gt;Redundancy leeches.&lt;/b&gt;  These people want to back up their files
(encrypted) to your computer for added redundancy.  Unfortunately, you gain
nothing by doing this for them; there's no way to force a leech to
contribute space back to other leeches. So these tend to end up as for-profit
services.  &lt;i&gt;(Examples: AllMyData, Dropbox, S3.)&lt;/i&gt;
&lt;p&gt;
3. &lt;b&gt;Sharers.&lt;/b&gt;  These people have data they want to share with
other people.  They benefit by &lt;i&gt;giving&lt;/i&gt; you the data; you benefit by
&lt;i&gt;receiving&lt;/i&gt; the data, and if you like it, you'll feel nice by sharing
it further.  &lt;i&gt;(Examples: Debian, Wikipedia, BitTorrent.)&lt;/i&gt;
&lt;p&gt;
(Free) distributed storage systems in groups 1 and 2 don't seem to ever
succeed, because there's no network growth effect.
&lt;p&gt;
Systems in group 3 succeed regularly.  And they don't need encryption.
      </description>
    </item>
    <item>
      <title>Why alienating developers is a winning strategy</title>
      <pubDate>Wed, 21 Apr 2010 00:05:55 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201004#21</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201004#21</guid>
      <description>&lt;p&gt;
I love this new iPhone SDK rule - the one that says you have to write all
your apps in pure Objective C with no translation layers.  Not because it's
good for me (it isn't), but because it's fun to watch an old-school titan -
Apple - play the platform game like they mean it.  There hasn't been fun
like this since Bill Gates left Microsoft.&lt;sup&gt;1&lt;/sup&gt;
&lt;p&gt;
Here's the story so far:
&lt;p&gt;
&lt;ol&gt;
&lt;li&gt;Lots of people bought iPhone 1.0 (without apps) because it was inherently awesome.
&lt;li&gt;Lots of people developed apps for it because there were so many users *and* it was awesome.
&lt;li&gt;About 10x more people bought it because it was even more awesome because of all the apps.
&lt;li&gt;Every other platform (hi, Android) is inferior because it has fewer users and developers and thus apps.&lt;sup&gt;2&lt;/sup&gt;
&lt;li&gt;Go back to step 2 and repeat.
&lt;/ol&gt;
&lt;p&gt;
(You might have seen this story before; see Crossing the Chasm and its
highly-relevant-to-this-discussion sequel, &lt;a
href=&quot;http://www.amazon.ca/Inside-Tornado-Marketing-Strategies-Silicon/dp/0887308244&quot;&gt;Inside the
Tornado&lt;/a&gt;.)
&lt;p&gt;
Then, suddenly, Apple clamped down even further on its SDK and app
store.&lt;sup&gt;3&lt;/sup&gt; Shocking!  People argue that this breaks the positive
feedback cycle: this will mean fewer developers, which means fewer apps,
which means less awesome, which means fewer users, which means other
platforms can compete, and so on.
&lt;p&gt;
No.
&lt;p&gt;
Here's the paradox.  Apple &lt;i&gt;does&lt;/i&gt; need developers to maintain
the cycle of awesomeness.  What Apple's doing is &lt;i&gt;not&lt;/i&gt; good for
developers.  And developers will continue the cycle anyway.
&lt;p&gt;
This is why:
&lt;p&gt;
Apple owns the platform; if their platform wins, they win bigger than
anybody else.  All they need to do to win is to continue to deliver
awesomeness to end users as fast as possible so that nobody can catch up. 
Because they're the biggest platform, they have the most money, so this
isn't that hard to do.
&lt;p&gt;
The other players are the end users.  They have to buy Apple stuff in order
for the cycle to continue.  The awesomeness must be there or they won't
buy stuff.  Java and Flash are the opposite of awesomeness.  Thus, Apple
rejects them outright.&lt;sup&gt;4&lt;/sup&gt;
&lt;p&gt;
Developers are not part of the strategy.  As a developer, you don't
make decisions based on awesomeness at all.  You might think you do, and the
first iPhone developers (&quot;early adopters&quot;) did, but that's not you.  The
modern developers, the ones with the pre-made market and fully-debugged SDK
and profitable clients paying you to write iPhone apps, build for iPhone
&lt;i&gt;only&lt;/i&gt; because it's the leading platform.
&lt;p&gt;
In the long term, developers like you would be better off if they would
boycott Apple and only develop awesome apps for something more open, like
Android or even Blackberry.&lt;sup&gt;5&lt;/sup&gt; Users, as they do, would rapidly
switch to the platform with the widest variety of awesome stuff, and
everybody would win.
&lt;p&gt;
But you aren't going to do that, are you?  Because nobody else will either. 
&lt;b&gt;Unless &lt;i&gt;all&lt;/i&gt; the developers switch, the only developers who switch
will be suckers.&lt;/b&gt; You don't want to be a sucker.  You want to make as
much money in the short term before the whole thing inevitably implodes. 
Because it &lt;i&gt;will&lt;/i&gt; implode, right?  &lt;i&gt;...right?&lt;/i&gt;
&lt;p&gt;
Microsoft won on the desktop by being developer-friendly and Apple won in
mobile by being developer-hostile.  Developers never had anything to do with
it.
&lt;p&gt;
&lt;b&gt;Footnotes&lt;/b&gt;
&lt;p&gt;
&lt;sup&gt;1&lt;/sup&gt; The closest we have right now is Google vs. Yahoo vs. 
Microsoft, ie.  a bunch of clueless losers shaking their fists at each
other.  Google isn't winning in search/advertising because of their awesome
strategy; they're winning because the competition keeps producing crap. 
Which is an okay reason to win, but it's not thrilling.  Apple vs.  World is
thrilling.
&lt;p&gt;
&lt;sup&gt;2&lt;/sup&gt; Actually #4 isn't even strictly true; last I heard, there are
still way more Blackberries than iPhones in active use.  But people
&lt;i&gt;believe&lt;/i&gt; it's true, which is all that matters for this discussion.
&lt;p&gt;
&lt;sup&gt;3&lt;/sup&gt; To be honest, the Apple app store was kinda fascist from day 1,
so we're just comparing on a relative scale here.  But people get upset
anyway.
&lt;p&gt;
&lt;sup&gt;4&lt;/sup&gt; All apps written in Java or Flash are ugly and stupid, so end
users benefit directly from this restriction.  Another reason for Apple to
reject such cross-platform apps is admittedly self-serving: if you own the
leading platform, you will always get the app.  So if you make it hard to
port apps between platforms, you're sabotaging the other platforms, not
yours.
&lt;p&gt;
&lt;sup&gt;5&lt;/sup&gt; Ha ha, I just called the Blackberry &quot;open,&quot; even though the
only language you could use to develop apps for it for &lt;i&gt;years&lt;/i&gt; has been
Java.  Somehow Java people manage to spin horrible restrictions as
features.  &quot;100% Pure Java!&quot; and so on.
      </description>
    </item>
    <item>
      <title>I may be internet famous, but I am not a primary source of original research</title>
      <pubDate>Sat, 17 Apr 2010 04:51:58 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201004#17</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201004#17</guid>
      <description>&lt;p&gt;
Particularly if you're thinking of footnoting my &lt;a
href=&quot;http://apenwarr.ca/log/?m=199505&quot;&gt;high school English essay&lt;/a&gt; as
&lt;a href=&quot;http://books.google.ca/books?id=Tt5etgx7cyEC&amp;pg=PA260&amp;dq=apenwarr&amp;cd=3#v=onepage&amp;q=apenwarr&amp;f=false&quot;&gt;one
of your references&lt;/a&gt; in a book about high-bandwidth network
communications.
&lt;p&gt;
Yeah, I remember my teacher gave me a 10/10 on that one.  15 years ago.  But
seriously.
&lt;p&gt;
(Thanks to Eduardo for pointing out what happens when you search for
&quot;apenwarr&quot; or &quot;Avery Pennarun&quot; in Google Books.  Answer: silly things.)
      </description>
    </item>
    <item>
      <title>Open source is stupid</title>
      <pubDate>Thu, 08 Apr 2010 21:58:00 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201004#09</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201004#09</guid>
      <description>&lt;p&gt;
Not the software.  The people.  And not the people who &lt;i&gt;make&lt;/i&gt; the
software.  The people who comment about it.  I guess now that includes me,
which is appropriate, since writing this post will obviously have no
positive outcome.
&lt;p&gt;
Background: I love Linux.  I've written far more Linux software (commercial
and open source) than software for any other platform.  Back in the 1990's,
I even &lt;a href=&quot;http://apenwarr.ca/arcnet/howto/intro.html&quot;&gt;wrote a Linux
kernel driver and poem&lt;/a&gt; that's (to my ongoing dismay) still in use today.
&lt;p&gt;
So yesterday's random post, in which I said something nice about Apple,
naturally tagged me instantly as an &quot;&lt;a
href=&quot;http://news.ycombinator.com/item?id=1249829&quot;&gt;Apple Fanboy&lt;/a&gt;.&quot; (Of
course, the accuser here is &quot;somewhat of an exception&quot; because he &quot;really
loves Linux.&quot;  Uh huh.  Yay you.)
&lt;p&gt;
By the way, yes, thank you for asking, I do have a Blackberry, and I have
used the SDK, and the Blackberry simulator is 100% pure crap compared to the
iPhone simulator.  This is obvious after 0.5 seconds of comparing the two,
after which the iPhone one has finished loading your app and the Blackberry
one hasn't even made its window appear yet, let alone booted the simulated
Blackberry OS.
&lt;p&gt;
Nevertheless, it's true. I am probably officially an Apple fanboy now.  I
mean, I've had an iPod since 2005, which is nearly the beginning of time.  I
even upgraded to an iPod Touch recently.  Also I have a Mac laptop because
&lt;a href=&quot;http://apenwarr.ca/log/?m=200610#24&quot;&gt;they're the only ones where
power management actually works&lt;/a&gt;.  Plus I totally downloaded their SDK
last week.
&lt;p&gt;
Speaking of which, XCode sucks.
&lt;p&gt;
Anyway.  Fanboy.  Yes.  Probably.  I do have to admit that it's interesting
following along with the whole Evil/Artist dichotomy.  Or is it a dichotomy
at all?  I mean, how can you be a serious artist and then let people use
Java?  Yes, Android, I'm talking to you.
&lt;p&gt;
And oh, speaking of Android.  While I'm flaming people needlessly, let me
just add one more thing:
&lt;p&gt;
&lt;b&gt;Top 10 Paid apps in the Android App Store&lt;/b&gt;
&lt;p&gt;
See the list &lt;a href=&quot;http://www.android.com/market/paid.html&quot;&gt;here&lt;/a&gt;.
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Abduction! World Attack: 2D game in 1980's style, but with more colours.
&lt;/li&gt;
&lt;li&gt;Power Manager: because multitasking kills your battery.
&lt;/li&gt;
&lt;li&gt;Baseball Superstars: they're afraid to show any screenshots.
&lt;/li&gt;
&lt;li&gt;Open Home: Replace your home screen to further reduce usability.
&lt;/li&gt;
&lt;li&gt;Jewellust: a Bejewelled clone.  Guess Bejewelled guys didn't bother.
&lt;/li&gt;
&lt;li&gt;MyBackup Pro: like backing up with iTunes, only not free.
&lt;/li&gt;
&lt;li&gt;Tangram Pro: something Chinese.
&lt;/li&gt;
&lt;li&gt;aHome: Yes, another one. Replace your home screen replacement.
&lt;/li&gt;
&lt;li&gt;dxTop: Oh look!  3/10 of the top paid apps replace the home screen!
&lt;/li&gt;
&lt;li&gt;Aevum Obscurum: the ancient game of Risk, only now you get to pay for it.
&lt;/li&gt;
&lt;/ul&gt;
Looking at the top 10 free apps is even more apalling.  The top 10 free
arcade/action games include Pac Man, Tron, Rescue Copter (with realistic
1980's 4-colour graphics!), BrickBreaker, Nibbles, and worse.  I'm not
kidding about worse.
&lt;p&gt;
Remember, folks, Google is the worldwide expert at showing the very best
stuff at the top of your search list.  Just think what the next 10 look
like!
&lt;p&gt;
Guys.  This is what happens when you let Java people write apps for your
platform.  Who's evil, again?
&lt;p&gt;
&lt;b&gt;Top 10 Paid apps in the Apple App Store&lt;/b&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;The Simpsons(tm)
&lt;/li&gt;
&lt;li&gt;Mega Man(tm) II
&lt;/li&gt;
&lt;li&gt;Scrabble(tm)
&lt;/li&gt;
&lt;li&gt;Monopoly(tm)
&lt;/li&gt;
&lt;li&gt;The Sims(tm) 3
&lt;/li&gt;
&lt;li&gt;Bejeweled(tm) 2
&lt;/li&gt;
&lt;li&gt;plus some garbage
&lt;/li&gt;
&lt;/ul&gt;
Oddly, the ridiculously addictive and awesome &lt;a
href=&quot;http://itunes.apple.com/ca/app/space-miner-space-ore-bust/id353853276?mt=8&quot;&gt;Space
Miner&lt;/a&gt; isn't even in the top 10.
&lt;p&gt;
You will note that Apple actually &lt;i&gt;explicitly prohibits Java developers
from coming anywhere near their SDK&lt;/i&gt;.  It's part of the license.  I'm not
even kidding.  This is not a coincidence.
&lt;p&gt;
There.  Glad I got that out of my system.
&lt;p&gt;
&lt;b&gt;apenwarr.&lt;/b&gt; Lowering the quality of discussion since... the 1990's
sometime.  Aw, who can remember exactly when.  Whatever.      </description>
    </item>
    <item>
      <title>How to run an iPhone app in the simulator without using XCode</title>
      <pubDate>Thu, 08 Apr 2010 19:08:52 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201004#08</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201004#08</guid>
      <description>&lt;p&gt;
I spent a lot of time looking around on the Internet for this answer, and
the results were basically nonexistent.  The answer is: &lt;a
href=&quot;http://github.com/jhaynie/iphonesim&quot;&gt;iphonesim&lt;/a&gt; on github. 
(Despite its name, iphonesim isn't an iPhone simulator; you still need the
iPhone SDK to be installed so it can use &lt;i&gt;their&lt;/i&gt; simulator.)
&lt;p&gt;
The bad news is there's no obvious way to run your app in a Debugger using
this system.  Hopefully someday it'll be added or I'll figure it out, and
then I'll be rid of XCode for good.
&lt;p&gt;
&lt;b&gt;Why the iPhone Simulator is Awesome&lt;/b&gt;
&lt;p&gt;
While we're here, I'm very impressed by the whole concept on which the
iPhone simulator works.  Most embedded devices (including Blackberry,
Android, and other phones) use software to emulate the embedded CPU, which
then runs the embedded OS, which then runs your app.  This kind of sucks,
because the emulator has to work really hard (it often runs at only a
fraction of the speed of a real device), and if you crash it you have to
reboot it.  Plus loading apps onto a simulated device is extra crappy,
because you have to simulate a slow USB connection, and so on.
&lt;p&gt;
The iPhone simulator works nothing like that.  Instead, you compile your app
for your &lt;i&gt;native&lt;/i&gt; CPU, and they made the iPhone simulator just a
&lt;i&gt;native&lt;/i&gt; program that runs on your workstation and provides the iPhone
API (using &lt;i&gt;native&lt;/i&gt; libraries).  You simulate and test your program,
and when you're finally happy with it, you recompile your app for the
target CPU that actually runs on an iPhone.  Then it won't work on the
simulator anymore.
&lt;p&gt;
The result is that the simulator starts &lt;i&gt;instantly&lt;/i&gt; and there's no
insane two-layer debugging scheme in which you're running a native debugger
and decoding non-native (and usually JITted) CPU instructions.
&lt;p&gt;
Some people would argue that this method is &quot;less accurate&quot; than precisely
emulating the target CPU, and thus the simulator doesn't add much value,
since you'll have to test the native app in the end anyhow.  It's true that
simulating this way is inaccurate and you should do final tests on a real
device.  The misconception, though, is that the old, annoying, slow,
&quot;emulate everything&quot; method is any &lt;i&gt;more&lt;/i&gt; accurate.  In fact, it's
worse.
&lt;p&gt;
The fact is, emulators are never perfect.  CPU/hardware emulators are
&lt;i&gt;really&lt;/i&gt; hard to get right, especially if you're trying to make them
run fast.  If you're &lt;i&gt;not&lt;/i&gt; trying to make them run fast, you have a
whole different set of problems, because now your simulator is way slower
than the real device, so all the animations/etc will be wrong.  Try
debugging an OpenGL app when your framerate is 1/10th what it should be.
&lt;p&gt;
By contrast, the iPhone simulator's method seems magically wonderful.  Since
the iPhone OS &lt;i&gt;is&lt;/i&gt; MacOS, all the kernel APIs are the same.  The
natively-compiled frameworks, libraries, and display engine are &lt;i&gt;built
from the same source code&lt;/i&gt;, so you know they're the same too.  And your
Mac's CPU is a lot faster than the iPhone's CPU, so the simulator can slow
down your program to iPhone speed, which is a lot easier than speeding it
up (although admittedly imperfect).
&lt;p&gt;
In fact, with this method, the only potential sources of incorrect
simulation are a) speed (which they seem to have gotten right); b)
cross-platform bugs in gcc (I don't know of any); or c) differences in
memory layout making memory corruption behave differently.  (c) could be a
problem, but they seem to provide a lot of debugging tools and you shouldn't
be depending on memory corruption anyhow.
&lt;p&gt;
Incidentally, this design justifies the fact that you have to have a Mac to
do iPhone development, and you have to have the latest MacOS (Snow Leopard)
to run the latest SDK.  This annoyed me when I first heard of it; I thought
Apple was just trying to lock more people into buying a Mac.  But now it
totally makes sense: iPhone OS *is* Snow Leopard, so if you want to run the
native simulator, of course you need Snow Leopard, or the simulator can't
possibly work.
&lt;p&gt;
That's a really brilliant design tradeoff with huge benefits.  &lt;i&gt;And&lt;/i&gt;
they get to lock more people into buying a Mac.
&lt;p&gt;
&lt;b&gt;Update 2010/04/08:&lt;/b&gt; A few people have pointed out that the Blackberry
&quot;emulator&quot; is apparently not actually an &quot;emulator&quot; but in fact runs a
natively-compiled version of the Blackberry JVM.  Okay, I guess, but that's
not really the point.  The point is that it still spends upwards of 30
seconds &lt;i&gt;booting&lt;/i&gt; the &quot;virtual Blackberry&quot; before it even gets to the
point where you can run your program.  (And you have to do this &lt;i&gt;every&lt;/i&gt;
time you want to run your program.) This is annoying, slow, and pointless,
and the (apparently native??) JVM still runs everything horrendously slowly -
slower than a real Blackberry.  So if it's not a native device emulator,
then congratulations, it's somehow even stupider.  Yes, I've done real
Blackberry development, and the difference between the Blackberry and iPhone
simulators is night and day.
      </description>
    </item>
    <item>
      <title>Dear StartupCampMontreal:</title>
      <pubDate>Wed, 24 Mar 2010 18:55:49 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201003#24</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201003#24</guid>
      <description>&lt;p&gt;
You are not a &quot;camp.&quot;  You are a &quot;conf.&quot;
&lt;p&gt;
The xxxCamp naming scheme appears to have originated with O'Reilly's
&quot;FooCamp,&quot; which was an informal event where a bunch of famous techie people
came to discuss stuff.  The more commonly known &quot;BarCamp&quot; series was created
as a backlash to the invitation-only FooCamp, but in the same &quot;unconference&quot;
style.  Thus, the &quot;xxxCamp&quot; series of events is defined primarily by its
unconference attributes, to wit:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Poorly organized (in a good way)
&lt;/li&gt;
&lt;li&gt;Informal
&lt;/li&gt;
&lt;li&gt;No prearranged agenda
&lt;/li&gt;
&lt;li&gt;More conversations than presentations
&lt;/li&gt;
&lt;li&gt;No cabal of unelected organizers who decides who gets to speak
&lt;/li&gt;
&lt;li&gt;No keynote presentations
&lt;/li&gt;
&lt;li&gt;No direct financial upside for any participants
&lt;/li&gt;
&lt;/ul&gt;
StartupCampMontreal claims to have an &quot;unconference component,&quot; but this
component is obviously a second-class citizen.  Among the many reasons that
this is obvious (from my observations when I attended it last year), one is
especially egregious: the unconference portion is from 1pm to 6pm in the
afternoon... &lt;i&gt;on a weekday&lt;/i&gt;.
&lt;p&gt;
It's reasonably possible for many people to get a day off work to go to a
conference; company-sponsored &quot;professional development&quot; days are common. 
Getting a free day off to go to an &lt;i&gt;unconference&lt;/i&gt; is very unlikely. 
And you know this, because you put the &quot;core&quot; (non-unconference, ie.
conference) part of your so-called camp in the evening, when people will be
easily able to attend.
&lt;p&gt;
I don't actually like &quot;conferences.&quot;  I find them tedious.  Keynote
speakers, no matter how famous, are almost universally cliches. 
Presentations selected by a cabal of organizers are almost never the
presentations that would have been selected by an audience (as they do at &lt;a
href=&quot;http://barcamp.org/StartupCampWaterloo&quot;&gt;StartupCampWaterloo, which is
a real &quot;camp&quot;&lt;/a&gt;) - they are therefore boring.  And a highly structured set
of presentations leaves little time for socializing and unstructured
discussion, which is the main purpose of an unconference.
&lt;p&gt;
Basically, StartupCampMontreal is not actually interesting to me, because it
is not actually a StartupCamp.  Your name is essentially false advertising.
&lt;p&gt;
Your conference is well organized, well marketed, smoothly running, and
attracts a lot of people including numerous sponsors, reasonably famous
keynote speakers, and an ever-increasing number of attendees.  I'm sure that
many of those people are happy to go to Startup&lt;b&gt;Conf&lt;/b&gt;Montreal, and I'm
not suggesting that you change your format just for me.
&lt;p&gt;
But what &lt;i&gt;I&lt;/i&gt; want and expect from a Startup&lt;b&gt;Camp&lt;/b&gt; is an
unconference.  This is why I will not be attending StartupCampMontreal in
the future.
&lt;p&gt;
Best of luck and have fun,
&lt;p&gt;
Avery
      </description>
    </item>
    <item>
      <title>bup is now more popular than all my other projects combined</title>
      <pubDate>Wed, 03 Mar 2010 21:27:20 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201003#03</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201003#03</guid>
      <description>&lt;p&gt;
...at least if you measure it by counting &lt;a
href=&quot;http://github.com/apenwarr&quot;&gt;the number of watchers on github&lt;/a&gt;.
&lt;p&gt;
It is also featured in the top 100 or so &lt;a
href=&quot;http://github.com/repositories&quot;&gt;interesting github repositories&lt;/a&gt;,
although there's no particular indication of what they mean by
&quot;interesting.&quot;
&lt;p&gt;
(Previously: &lt;a&gt;&lt;a href=&quot;http://apenwarr.ca/log/?m=201001#04&quot;&gt;bup: it backs
things up&lt;/a&gt;. It's matured quite a bit since then, though, and is now
usable for backing up real work that you care about.)
&lt;p&gt;
      </description>
    </item>
    <item>
      <title>Things that are best lost in translation</title>
      <pubDate>Sun, 24 Jan 2010 08:52:14 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201002#12</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201002#12</guid>
      <description>&lt;p&gt;
&lt;ul&gt;&lt;i&gt;A clever Toronto lawyer was deep into a technical argument before the
Supreme Court.  His position was dependent upon a close reading of the legal
text and turned on the letter of the law.
&lt;p&gt;
Suddenly the chief justice,
Beverley McLachlin, leaned forward and asked if his argument also worked in
French.  After all, the law is the law in both languages and a loophole in
one tends to evaporate in the other.  Only an argument of substance stands
up. ... Reality seen through two languages can protect us from the demeaning
of justice by technical acrobatics.&lt;/i&gt;&lt;p&gt;-- John Ralston
Saul, &lt;a href=&quot;http://www.johnralstonsaul.com/SUM_AFC.html&quot;&gt;A Fair
Country&lt;/a&gt; (p.128)&lt;/ul&gt;
&lt;p&gt;
Parallel with the IETF's &quot;&lt;a
href=&quot;http://www.ietf.org/iesg/implementation-report.html&quot;&gt;at least two
independent and inter-operable implementations&lt;/a&gt;&quot; rule.
      </description>
    </item>
    <item>
      <title>The problem with the iPad is it has no ethernet ports or DVD drive</title>
      <pubDate>Mon, 01 Feb 2010 21:20:08 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201002#08</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201002#08</guid>
      <description>&lt;p&gt;
...just kidding.  But those were the main reasons people gave when they
decided the MacBook Air wouldn't be successful a couple of years ago.
&lt;p&gt;
It's very interesting that in a laptop, those two features are considered
critical.  In a &quot;tablet,&quot; they apparently are not.
&lt;p&gt;
This sounds like classic &quot;positioning&quot; in marketing: since you don't know
what a table computer is, you don't have expectations.  Since you know what
a laptop is, you do.  I have a MacBook (not Air).  I don't remember the last
time I used the ethernet port or the DVD drive.  But I wouldn't have bought
it without them.
&lt;p&gt;
Or maybe the difference is just that the tablet is cheap, and the Air was
expensive.
      </description>
    </item>
    <item>
      <title>A git-subtree tutorial</title>
      <pubDate>Thu, 04 Feb 2010 19:43:11 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201002#04</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201002#04</guid>
      <description>&lt;p&gt;
Jakub Suder has a nice &lt;a
href=&quot;http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/&quot;&gt;tutorial
on how to use my git-subtree tool&lt;/a&gt; to manage git repositories that track
other projects in subdirs.
&lt;p&gt;
It's quite nicely written, and unlike my own documentation, it has pretty
diagrams.
&lt;p&gt;
      </description>
    </item>
    <item>
      <title>Democracy - the hard way</title>
      <pubDate>Sun, 24 Jan 2010 08:52:26 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201002#02</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201002#02</guid>
      <description>&lt;p&gt;
&lt;ul&gt;&lt;i&gt;The great fear of the founders of the United States was that, having
created their country out of a violence that papered over the country's
fundamental internal contradictions ... it would break apart again.  And it
would do so violently.  They were right to be afraid, as that was preciely
what happened some 75 years later.
&lt;p&gt;
That original fear of the founders still
lies at the heart of nationalism in the United States and still drives the
country's idea of citizenship expressed through loyalty.&lt;/i&gt;&lt;p&gt;-- John
Ralston Saul, &lt;a href=&quot;http://www.johnralstonsaul.com/SUM_AFC.html&quot;&gt;A Fair
Country&lt;/a&gt; (p.139)&lt;/ul&gt;
      </description>
    </item>
    <item>
      <title>Democracy - the easy way</title>
      <pubDate>Sun, 24 Jan 2010 08:17:55 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201002#01</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201002#01</guid>
      <description>&lt;p&gt;
&lt;ul&gt;&lt;i&gt;Canada was the first colony in any empire to extract full democracy
from the central power without having to go to war.&lt;/i&gt;&lt;p&gt;-- John Ralston
Saul, &lt;a href=&quot;http://www.johnralstonsaul.com/SUM_AFC.html&quot;&gt;A Fair
Country&lt;/a&gt; (p.132)&lt;/ul&gt;
&lt;p&gt;
Definitely enjoying this book.
      </description>
    </item>
    <item>
      <title>More on prorogation</title>
      <pubDate>Tue, 26 Jan 2010 17:39:58 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201001#25</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201001#25</guid>
      <description>&lt;p&gt;
In response to &lt;a href=&quot;http://apenwarr.ca/log/?m=201001#23&quot;&gt;my previous post
about prorogation&lt;/a&gt;, someone emailed me this comment:
&lt;p&gt;
&lt;ul&gt;&lt;i&gt;My participation in our democracy is limited to voting when there's an
election and mostly ignoring everything else. [...] Despite that, I can tell
from the rumbling that there's something unusual about this particular
prorogation. &lt;b&gt;If it was just normal boring governing, nobody would be talking
about it.&lt;/b&gt;&lt;/i&gt;&lt;/ul&gt;
&lt;p&gt;
I actually think this comment is very insightful, because it gets right to
the heart of the issue I was trying to address.  Other people sent responses
that were more like, &quot;But what gives them the right to manipulate it in such
an evil way?&quot; It's almost the same question, but &lt;i&gt;those&lt;/i&gt;
comments were not insightful.  They missed the fact that there may not be
any manipulation at all, and therefore turned it from a question of fact
into a question of opinion.
&lt;p&gt;
I'm not a professional journalist.  Yesterday's attempt at factual reporting
took all the restraint I had.  So this post will surely not meet my own high
standards for journalistic integrity.  I'm just some guy on the Internet. 
You've been warned.
&lt;p&gt;
&lt;b&gt;How I came to know what &quot;prorogation&quot; means&lt;/b&gt;
&lt;p&gt;
Full disclosure: I personally don't like the Conservatives.  I think &lt;a
href=&quot;http://apenwarr.ca/log/?m=200812#04&quot;&gt;if they had a majority
government, Canada would be worse off&lt;/a&gt;.  I think the fact that Harper
does most of his public relations through a &quot;spokesperson&quot; is a total
embarrassment.  I also think our current batch of other political leaders,
with the possible exception of Gilles Duceppe, are even worse, and I sorely
miss the days when Jean Chretien used to beat people up with statues.
But I wouldn't vote for Ignatieff, precisely because he
pulls the current kind of crap.  I wish I still lived in Quebec so I'd at
least have a party worth voting for.
&lt;p&gt;
That's the perspective with which, not knowing anything about the current
prorogation debate (or even what &quot;prorogation&quot; means), I returned to Canada
from my vacation in Mexico and was met by an angry Internet mob
complaining about our upcoming dictatorship.
&lt;p&gt;
See above: &quot;My participation in our democracy is limited to voting when
there's an election and mostly ignoring everything else.&quot; Me too.  You know
why?  Because I think the system works.  That's the beauty of
&lt;i&gt;representative&lt;/i&gt; democracy.  But I figured, okay guys, I'm pretty
smart, I can figure this stuff out.  If there's really a dictatorship
coming, I want to be on the winning team.  So I thought I'd
better look into it.
&lt;p&gt;
The actual mob of complainers were no help.  They all figured that someone
&lt;i&gt;else&lt;/i&gt; knew what was bad about what was going on, or else they figured
that just suspending parliament at all made the government a dictatorship.
&lt;p&gt;
This left me to do my own &quot;research&quot; (a word that is in quotes because I
did all this &quot;research&quot; in bed using my laptop).
&lt;p&gt;
First stop: &lt;a href=&quot;http://www.nationalpost.com/story.html?id=2477642&quot;&gt;The
National Post&lt;/a&gt; (via Google), in an article titled, &quot;Thousands turn out at
rallies to protest proroguing of Parliament.&quot;
&lt;p&gt;
&lt;ul&gt;&lt;b&gt;Intermission: A note on how to read political news&lt;/b&gt;&lt;br&gt; All news
sources are biased.  The first thing you have to do is identify the bias. 
Both the National Post and the Globe and Mail are Liberal-friendly and
anti-Conservative.  How can you tell?  Just read &lt;i&gt;any headline about
politics&lt;/i&gt; and watch the trend.  Other tips: 1) all quotes from
politicians are weasel words; don't trust them.  2) using quotations from
any individual allow the newspaper to avoid fact checking; it is
&lt;i&gt;always&lt;/i&gt; a fact that &quot;person X said Y,&quot; no matter how false Y may be. 
3) in constructions like &quot;estimates pegged the turnout at more than 3000
people&quot; note that &lt;i&gt;nobody&lt;/i&gt; in particular is being quoted; they are
reporting that some random person estimated more than 3000 people.  Do not
fool yourself into thinking that they don't pull tricks like this.  They
have to research, write, edit, and publish a fat sheaf of paper like the
National Post &lt;i&gt;every single day&lt;/i&gt;.  Corners will be cut.&lt;/ul&gt;
&lt;p&gt;
...shockingly, the National Post headline is phrased in an anti-government
way (since the government is Conservative).  Reading on, we see lots of
quotes from political leaders (ignore them; rule 1).  The whole article is
also really a big quote from an angry mob of protesters (no fact checking
was done; rule 2), since it merely reports that there &lt;i&gt;was&lt;/i&gt; an angry
mob, not that what the mob was angry about even exists.  And we don't know
if the mob was really 10 people or a million people (rule 3).
&lt;p&gt;
So that article, although it used many words, was in fact 100% pure
unenlightening.
&lt;p&gt;
Nevertheless, I could feel myself thinking anti-Conservative thoughts
despite the total lack of facts.  I thought I'd better go find something
biased in the opposite direction so that I could balance things out a
little.  I realized that I couldn't think of any actual Canadian mainstream
newspapers that are Conservative-friendly; I'm probably forgetting something
obvious.
&lt;p&gt;
So I resorted to blogs, which made things easier.  Next stop: &lt;a
href=&quot;http://thealbertaardvark.blogspot.com/2010/01/prorogation-day-in-canada.html&quot;&gt;Alberta
Ardvark&lt;/a&gt; (via Google).  I have to admit that I assumed they were
Conservative-friendly just because they're in Alberta, which means I'm a
racist.  However, I was not disappointed.
&lt;p&gt;
That article was the usual politico-blogger nonsense, giving handy advice on
how to win a political argument not by arguing about the issue, but instead
by turning the conversation around to character assassination whenever
possible.  (In this case, it's about the fact that Ignatieff supported
prorogation last year, so he's not allowed to be against this particular
prorogation this year; that makes him inconsistent, therefore a liar, so it
doesn't matter what he says, etc.) Nicely done as always, Internet.  But
there was one intriguing quote: &quot;...the ones who have been convinced by the
media that &lt;a
href=&quot;http://thealbertaardvark.blogspot.com/2010/01/prorogue-score.html&quot;&gt;this
prorogation is not a routine event&lt;/a&gt;...&quot;
&lt;p&gt;
Wait... routine event?  Surely this is Conservative propaganda.  I was
intrigued, so I followed the link.
&lt;p&gt;
It points out that Chretien prorogued parliament 4 times.  And Pierre Elliot
Trudeau, supposed Canadian hero... 11 times?!  Holy crap!  Who's the evil
one around here, again?
&lt;p&gt;
My brain's magical pattern-detectors then kicked in and I thought: hey, wait
a minute.  Those prorogation counts seem to be roughly proportional to the
amount of time a particular Prime Minister was in office.  Perhaps there's a
pattern here.
&lt;p&gt;
And then, at the bottom of the article: &quot;In our 143 years of existence as
Canada, Parliament has been prorogued 105 times.&quot;
&lt;p&gt;
Oh dear. 
&lt;p&gt;
Maybe I'd better go &lt;a
href=&quot;http://www2.parl.gc.ca/MarleauMontpetit/DocumentViewer.aspx?Sec=Ch08&amp;Seq=7&amp;Lang=E&quot;&gt;learn
what prorogation is&lt;/a&gt;.  The answer is: it's an all-too-fancy word for the
end of &lt;i&gt;every&lt;/i&gt; parliamentary session.
&lt;p&gt;
And it's a word I didn't know the meaning of until now.  A word that every
news article and blog entry I've read so far has not bothered to define.  A
word that, in some tenses, has the word &quot;rogue&quot; in it.
&lt;p&gt;
Okay, this sucks.  Reading biased articles in a search for truth is getting
me nowhere.  Is there not &lt;i&gt;any&lt;/i&gt; news source that will just give me the
facts and not try to spin it the way they want?  Well, no, I guess there
isn't.  But there's something close: &lt;a
href=&quot;http://www.cbc.ca/politics/story/2009/12/30/parliament-prorogation-harper.html&quot;&gt;the
CBC&lt;/a&gt;.
&lt;p&gt;
Because it would be weird if they didn't, the above-linked CBC article has
quotes from politicians; try to ignore them (rule 1).  If you fail to do so,
you will discover that the first apparent use of the word &quot;despotic&quot; in this
context was by Ralph Goodale, Liberal House Leader, whom you should not vote
for because he is thus automatically a lunatic.
&lt;p&gt;
However, the non-politician-quote parts of the article seem to be well
balanced and, notably, identify several reasons why Harper might have wanted
to prorogue government &lt;i&gt;right now&lt;/i&gt; as opposed to some other time.
&lt;p&gt;
So what have we learned?  First, that prorogation of parliament is totally
normal, and that the length of the just-ended session isn't even unusually
short; and second, that Harper might very well have chosen this particular
date in order to benefit himself or his party.  Gasp!  Let us look at these
possible reasons in more detail.
&lt;p&gt;
&lt;b&gt;The CBC's suggested reasons for the current prorogation&lt;/b&gt;
&lt;p&gt;
&quot;Muzzle parliamentarians amid controversy over the Afghan detainees affair.&quot;
Don't know about you, but parliament has been shut down for a whole month
already and I haven't noticed any of those parliamentarians not talking.  I
wish.  But maybe you have a point; when parliament next starts up, I bet the
opposition parties will have completely forgotten about the whole thing,
despite the obvious political leverage they could gain from bringing it up. 
Harper has totally outfoxed them on this one.
&lt;p&gt;
&quot;To consult with Canadians, stakeholders and businesses as it moves into
the 'next phase' of its economic action plan amid signs of economic
recovery.&quot;  Well, I guess theoretically, if you're in parliament you don't
have as much time for consulting with Canadians.  But don't we have Royal
Commissions for that or something?  Maybe they just wanted a longer
Christmas holiday.  (Aside: the reason the prorogation &quot;doesn't start until
January 25th&quot; is that they've all been on holidays since sometime in
December.  Seriously.)
&lt;p&gt;
&quot;Strategically, prorogation also prevents question period criticisms from
the opposition parties during the Olympics.&quot;  Hey, not bad.  Avoid the bad
PR for Canada from discussing our idiotic foreign affairs policies at the
same time as we're in the global spotlight.  Critically,
this allows Mr. Harper, who (let's be honest) doesn't look all that lovable,
to hide in the cellar for the whole time the Olympics are on, letting someone
cuter represent us to the world.  This seems to be a wise strategy no matter
which side of the fence you're on.
&lt;p&gt;
&quot;By proroguing Parliament, he is unilaterally making a decision to stop any
kind of disclosure from happening.&quot;  As if information can't be disclosed
just because nobody's making any laws right now.  Remember: parliament is
the legislative branch of the government.  It's for making new laws.  No
other part of the government is suspended just because parliament is. 
(Note: see update below.)
&lt;p&gt;
&quot;Gilles Duceppe wrote that prorogation has become 'a tradition for Harper.'&quot;
Duceppe has an awesome sense of humour.  I had to read this
one a few times before I realized that he managed to give them a sound bite
while simultaneously making fun of the fact that prorogation is totally
normal, ie. a &quot;tradition.&quot;
&lt;p&gt;
&quot;By the time Parliament resumes, Harper would have had time to ask Jean to
name five new senators, which would give the Conservatives a majority on the
newly formed Senate committees and greater control for passing their own
legislation.&quot; (Notably: nobody was quoted saying this.  CBC had to look it
up on their own.) &quot;Soudas confirmed the prime minister will seek to fill the
Senate vacancies between now and March.&quot; This one is actually a great
example of a real political reason to prorogue parliament; to get more
control of the senate in time for the next session.  But the Canadian senate
system is &lt;i&gt;designed&lt;/i&gt; (on purpose) to work like that.  That's why the
current senate is mostly Liberal even though our elected representatives are
mostly non-Liberal.  Senators are appointed for life, at which time the
Prime Minister selects new ones.  No surprises here.
&lt;p&gt;
(In case you don't like that system: the only party in favour of senate
reform in Canada is the Conservatives.  They'd rather you could elect your
senators.  How &quot;anti-democratic&quot; of them.  I actually think such reform
would be a change for the worse, but that's just my opinion.)
&lt;p&gt;
&quot;Shortly after Soudas' announcement, the government sent out an email saying
it would reintroduce, in original form, the consumer safety bill and the
anti-drug-crime law that the Tories claimed the Liberals 'gutted' in the
Senate.&quot;  This shows significant political maneuvering.  However, bills take
multiple rounds through both houses before they (might) get passed anyway,
so this isn't as bad as it sounds.  The &quot;gutted&quot; version might never have
been passed anyway.  Also, interestingly, this was pointed
out in an email from a &lt;i&gt;Conservative&lt;/i&gt; MP.  Apparently &lt;i&gt;they&lt;/i&gt; don't
think it's evil.  At least not evil enough to cover up.
&lt;p&gt;
&lt;b&gt;Conclusions&lt;/b&gt;
&lt;p&gt;
Guys, I did my homework.  But I'm just not seeing it.  The actual facts are:
&lt;p&gt;
1) Prorogation is perfectly normal and the recent parliamentary session
wasn't abnormally short.
&lt;p&gt;
2) We won't have any more new laws getting made for a month or so longer
than usual.  (Remember: they were on vacation until January 25th anyway.)
But being unable to do stuff doesn't make you a despot, it makes you a
eunuch.
&lt;p&gt;
3) If Harper is really evil, the first thing to happen in the new parliament
in March is that there will be a vote of non-confidence followed by an
election.  If this doesn't happen, it's because the angry non-Conservative
parties didn't actually believe he was evil either.
&lt;p&gt;
4) There are some valid political reasons why it's better for the
Conservatives if they prorogue parliament right now instead of later. 
However, they aren't very exciting reasons.
&lt;p&gt;
5) There is at least one actual reason (Harper is scary-looking and the
Olympics are coming) that it's better for &lt;i&gt;Canada&lt;/i&gt; if they prorogue
parliament right now.
&lt;p&gt;
6) All mainstream media that I read - which was quite a bit - &lt;a
href=&quot;http://www.theglobeandmail.com/blogs/bureau-blog/london-prorogation-protest-skips-buckingham-heads-for-pub/article1442093/&quot;&gt;failed to
properly define the term &quot;prorogation&quot; or to mention that it's perfectly
normal&lt;/a&gt;.  This seems a rather critical thing to know.  Its omission suggests
to me that they're trying to make news out of non-news.
&lt;p&gt;
&lt;b&gt;Epilogue&lt;/b&gt;
&lt;p&gt;
&quot;If it was just normal boring governing, nobody would be talking about it.&quot;
&lt;p&gt;
Unfortunately not true.
&lt;p&gt;
That's textbook mob mentality: he must be guilty, because otherwise my
friends wouldn't be burning down his house.
&lt;p&gt;
The only cure for mob mentality is thinking for yourself.
&lt;p&gt;
&lt;b&gt;Updates&lt;/b&gt;
&lt;p&gt;
Some helpful people have emailed me to clarify or correct or question
various parts of the above.
&lt;p&gt;
&lt;b&gt;Information release on the Afghan torture investigation:&lt;/b&gt; make no
mistake, this investigation, and the demand for release of information
related to it, is very important.  It will also be delayed (for about
one month) because of prorogation.  Because of &quot;parliamentary immunity,&quot; the
interesting testimony won't be released during the delay.  However, you need
to think about two key points: first, will the end result of the
investigation be any different because of a one-month delay?  And second:
will the Conservatives benefit because of the delay?  Keep in mind that if
the results came out &lt;i&gt;now&lt;/i&gt;, they would be largely overshadowed by news
about the Olympics.  If they come out &lt;i&gt;later&lt;/i&gt;, the Olympics will be
over, the opposition parties could force an election, and the results would
be headlining right as we're thinking about who to vote for.  And yet the
Conservatives have chosen the latter, not the former.
&lt;p&gt;
&lt;b&gt;Precise timing of prorogation:&lt;/b&gt; Several people responded by claiming
that it's not prorogation that's the problem, it's the particular timing of
Harper's use of prorogation.  This is an insidious line of argument because
it's impossible to disprove; if Harper had prorogued parliament back on the
9th of September (9/9/9 is the British equivalent of 9/1/1), you could have
accused him of using numerology to choose prorogation dates, and it would be
&lt;i&gt;impossible to refute that claim&lt;/i&gt;, even if it had been a perfectly
sensible date to end the parliamentary session.  Thus, to demonstrate any
wrongdoing, you really have to be more specific about why the current timing
is so evil.  I have discussed several possible reasons above.  Please feel
free to suggest more.  But &quot;the timing is evil!&quot; is not specific enough.
&lt;p&gt;
With that in mind, however, a lot of bad statistics are being spread with
regard to the lengths of various parliamentary sessions.  Here are &lt;a
href=&quot;http://www2.parl.gc.ca/Parlinfo/Lists/Parliament.aspx?Language=E&quot;&gt;all of
the sitting days per session since 1980&lt;/a&gt;:
&lt;p&gt;
Turner and Trudeau (Liberal): 591, 116&lt;br&gt;
Mulroney (Conservative): 308, 389, 11, 308, 271&lt;br&gt;
Chretien (Liberal): 283, 164, 243, 133, 211, 143 (avg: 196)&lt;br&gt;
Martin (Liberal): 55, 159&lt;br&gt;
Harper (Conservative): 175, 117, 13, 128 (avg. excluding outlier: 140)
&lt;p&gt;
Eyeballing it, Harper's numbers are &lt;i&gt;very slightly&lt;/i&gt; lower than typical
(except for last year's prorogation, which was indeed an interesting event).
Ignoring the outlier (13), Harper's average is just 29% lower than
Chretien's. However, Harper has also managed to hold together the
longest-running (by a large margin) minority government in Canadian history.
I find it unsurprising that the effort required to do so would result in
somewhat shorter sessions.
      </description>
    </item>
    <item>
      <title>Proroguing parliament</title>
      <pubDate>Sun, 24 Jan 2010 07:11:07 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201001#23</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201001#23</guid>
      <description>&lt;p&gt;
&quot;Prorogation&quot; is the &lt;a
href=&quot;http://www2.parl.gc.ca/MarleauMontpetit/DocumentViewer.aspx?Sec=Ch08&amp;Seq=7&amp;Lang=E&quot;&gt;term
we use to describe the end of any session of parliament in Canada&lt;/a&gt;.
&lt;p&gt;
Or as the Canadian Parliament web site says, &quot;&lt;a
href=&quot;http://www.parl.gc.ca/compendium/web-content/c_g_parliamentarycycle-e.htm#3&quot;&gt;Each
session of a Parliament ends with the prorogation of Parliament by the
Governor General, on the advice of the Prime Minister&lt;/a&gt;.&quot;
&lt;p&gt;
Since Canada's confederation in 1867 (143 years ago), parliament has
prorogued 105 times.  That's an &lt;i&gt;average&lt;/i&gt; of about 1.4 years per
session (some are longer, some are shorter).
&lt;p&gt;
See the &lt;a
href=&quot;http://www2.parl.gc.ca/Parlinfo/Lists/Parliament.aspx?Language=E&quot;&gt;Government
of Canada's complete list of prorogations&lt;/a&gt;.
&lt;p&gt;
Use of the term &quot;despotic&quot; in this context makes you automatically a
lunatic.
&lt;p&gt;
That is all.
      </description>
    </item>
    <item>
      <title>The Google Phone</title>
      <pubDate>Wed, 06 Jan 2010 23:55:58 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201001#07</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201001#07</guid>
      <description>&lt;p&gt;
&lt;ul&gt;...even Microsoft never was brazen enough to pull something like this. Even
Microsoft had some tiny bit of shame. Google is a different beast
altogether. They're like nothing anyone has ever seen in our business. Not
only are they not ashamed - &lt;i&gt;they think they're the good guys!&lt;/i&gt;&lt;p&gt;-- &lt;a
href=&quot;http://www.fakesteve.net/2010/01/im-trying-to-remember-how-many-times-eric-swore-to-me-that-google-would-never-make-a-phone.html?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+TheSecretDiaryOfSteveJobs+%28The+Secret+Diary+of+Steve+Jobs%29&quot;&gt;Fake
Steve Jobs&lt;/a&gt;&lt;/ul&gt;
&lt;p&gt;
Dot dot dot.
      </description>
    </item>
    <item>
      <title>Dealing with "tumultuous" economic times</title>
      <pubDate>Sun, 03 Jan 2010 19:39:44 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201001#06</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201001#06</guid>
      <description>&lt;p&gt;
&lt;a href=&quot;http://lwsmith.ca/2010/01/these-tumultuous-times-2/&quot;&gt;Canadian
Economics Superhero Larry Smith&lt;/a&gt; has a new article out, addressing
burning economic question questions such as:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Why is Silicon Valley so shortsighted?
&lt;/li&gt;
&lt;li&gt;Why do so many people write iPhone apps and so few write medical software?
&lt;/li&gt;
&lt;li&gt;How to deal with a shortage of engineers.
&lt;/li&gt;
&lt;li&gt;Volume of information vs. value of information.
&lt;/li&gt;
&lt;/ul&gt;
All great stuff as always.  You should read it.
      </description>
    </item>
    <item>
      <title>bup 0.01: It backs things up</title>
      <pubDate>Sun, 24 Jan 2010 02:15:41 +0000</pubDate>
      <link>http://apenwarr.ca/log/?m=201001#04</link>
      <guid isPermaLink="true">http://apenwarr.ca/log/?m=201001#04</guid>
      <description>&lt;p&gt;
I just spent a few days of my Christmas vacation writing a new program, &lt;a
href=&quot;http://github.com/apenwarr/bup&quot;&gt;bup&lt;/a&gt;.
&lt;p&gt;
bup is a program that backs things up.  It's short for &quot;backup.&quot; Can you
believe that nobody else has named an open source program &quot;bup&quot; after all
this time?  Me neither.  It also has &lt;a
href=&quot;http://en.wikipedia.org/wiki/File:Bup.jpg&quot;&gt;almost&lt;/a&gt; no other
meanings.
&lt;p&gt;
Despite its unassuming name, bup is pretty cool.  To give you an idea of
just how cool it is, I wrote you this poem:&lt;center&gt;
&lt;p&gt;
                            Bup is teh awesome&lt;br&gt;
                          What rhymes with awesome?&lt;br&gt;
                            I guess maybe possum&lt;br&gt;
                           But that's irrelevant.&lt;br&gt;&lt;/center&gt;
&lt;p&gt;
Hmm.  Did that help?  Maybe prose is more useful after all.
&lt;p&gt;
&lt;b&gt;Reasons bup is awesome&lt;/b&gt;
&lt;p&gt;
bup has a few advantages over other backup software:
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;It uses a rolling checksum algorithm (similar to rsync) to &lt;a href=&quot;http://apenwarr.ca/log/?m=200910#04&quot;&gt;split large files into chunks&lt;/a&gt;.  The most useful result of this is you can backup huge virtual machine (VM) disk images, databases, and XML files incrementally, even though they're typically all in one huge file, and not use tons of disk space for multiple versions.
&lt;/li&gt;
&lt;li&gt;It uses the packfile format from &lt;a href=&quot;http://apenwarr.ca/log/?m=200801#31&quot;&gt;git&lt;/a&gt;, so you can access the stored data even if you don't like bup's user interface.
&lt;/li&gt;
&lt;li&gt;Unlike git, it writes packfiles *directly* (instead of having a separate garbage collection / repacking stage) so it's fast even with gratuitously huge amounts of data.
&lt;/li&gt;
&lt;li&gt;Data is &quot;automagically&quot; shared between incremental backups without having to know which backup is based on which other one - even if the backups are made from two different computers that don't even know about each other.  You just tell bup to back stuff up, and it saves only the minimum amount of data needed.
&lt;/li&gt;
&lt;li&gt;Even when a backup is incremental, you don't have to worry about restoring the full backup, then each of the incrementals in turn; an incremental backup *acts* as if it's a full backup, it just takes less disk space.
&lt;/li&gt;
&lt;li&gt;It's written in python (with some C parts to make it faster) so it's easy to extend and maintain.
&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Super quick example&lt;/b&gt;
&lt;p&gt;
(The &lt;a
href=&quot;http://github.com/apenwarr/bup/blob/master/README.md&quot;&gt;README&lt;/a&gt;
actually has a more detailed example.)
&lt;p&gt;
Try making a remote backup:&lt;pre&gt;
 	tar -cvf - /etc | bup split -r myserver: -n my-etc -vv&lt;/pre&gt;
 	
Try restoring your backup:&lt;pre&gt;
 	bup join -r myserver: my-etc | tar -tf -&lt;/pre&gt;
&lt;p&gt;
(On myserver) look at how much disk space your backup took:&lt;pre&gt;
 	du -s ~/.bup&lt;/pre&gt;
 	
Make another backup (yes, that's exactly the same command):&lt;pre&gt;
 	tar -cvf - /etc | bup split -r myserver: -n my-etc -vv&lt;/pre&gt;
&lt;p&gt;
Look how little extra space your second backup used on top of the
first:&lt;pre&gt;
 	du -s ~/.bup&lt;/pre&gt;
 	
Restore your *first* backup over again (the ~1 is git notation for &quot;one
older than the most recent&quot;):&lt;pre&gt;
   	bup join -r myserver: local-etc~1 | tar -tf -&lt;/pre&gt;
 
&lt;b&gt;What's next?&lt;/b&gt;
&lt;p&gt;
I have lots of plans for this lovely program, in the event that I
actually get time to implement them.  But if you think it's cool,
please feel free to git clone it, hack away, and send some patches! 
Read the &lt;a
href=&quot;http://github.com/apenwarr/bup/blob/master/README.md&quot;&gt;README&lt;/a&gt; for
a list of some deficiencies in the current release.
&lt;p&gt;
I'm sure there are also more deficiencies that I don't know about, of course.
&lt;p&gt;
(&lt;a href=&quot;http://apenwarr.ca/log/?m=200708#08&quot;&gt;Previous poetry-related
adventures&lt;/a&gt;.)
&lt;p&gt;
&lt;b&gt;Update (2010/01/05):&lt;/b&gt; Commentary at &lt;a
href=&quot;http://news.ycombinator.com/item?id=1029990&quot;&gt;ycombinator news&lt;/a&gt; and
&lt;a
href=&quot;http://www.reddit.com/r/programming/comments/aljfk/bup_001_it_backs_things_up/&quot;&gt;reddit
programming&lt;/a&gt;.  To answer the most common question: it's different from
most of those other apps you mention because: a) bup backs up really huge
files rather than silently ignoring them or running out of memory;
b) bup is a backend, not a GUI, while most of those apps are GUIs
(which could use bup as a backend if they wanted); c) bup stores its backups
in big packfiles, rather than a one-file-per-file model, and thus can be
much faster (but 0.01 isn't optimized yet).
&lt;p&gt;
&lt;b&gt;Update 2 (2010/01/05):&lt;/b&gt; By popular demand (well, nonzero demand from
the populace, anyway), I've created a &lt;a
href=&quot;http://groups.google.com/group/bup-list/&quot;&gt;mailing list&lt;/a&gt;.  You can
subscribe by sending an email to bup-list+subscribe@googlegroups.com (note
the weird + character in the email address).
      </description>
    </item>
  </channel>
</rss>
