Fair

and "balanced"
Everything here is my opinion. I do not speak for your employer.
November 2007
January 2008

2007-12-01 »

Sanity and Climate Change

My friend and former engineering classmate David Pritchard writes a summary of a book on global warming and compares it to a related scientific paper.

I really like David's analysis. It's short enough to be readable in a few minutes, but long enough to have actual content. It also states far more facts than opinions, leaving you to make conclusions for yourself.

I took one key point away from reading it. Maybe it's obvious to you, but it was never obvious to me, and it seems not to be obvious to a lot of coffee table environmentalists. The point is just this: our goal needs to be to stabilize the atomospheric carbon level.

Does that sound too obvious? Think about what else it means:

  • It doesn't matter whether the carbon level increase is caused by mankind or not. There are arguments that global warming/cooling happens on a natural cycle. Answer: irrelevant. Stabilizing it won't make things worse, and it might make things better. (Dinosaurs probably didn't cause an ice age, either, but that didn't make it any more comfortable for them.)

  • It doesn't really matter whether the carbon level increase affects the temperature, or how much. An increase in carbon levels in the atmosphere might have all sorts of effects we don't know about; just keep it the same, and we risk nothing. The same can be said for most of the arguments about positive/negative feedback loops, etc.

  • You don't have to stop emitting carbon. Too little carbon would be just as bad as too much. Remember, things are absorbing it again. You just have to keep things in equilibrium.

  • You can keep things in equilibrium by increasing carbon "sinks" as well as by decreasing emissions.

This is a gross oversimplification and David's article says many other important things in a clear and well-balanced way, and includes references. You should read it.

2007-12-02 »

Weather report

The weather today reminds me of Web 2.0. Today the conditions are just right to roll huge snowballs fast, but tomorrow they can just as easily melt down. :)

2007-12-06 »

Canada: SRED Tax Credits

2008 may be the year when I personally change from a "cost center" to a "profit center" at my company as I help with our R&D tax credits report.

Basically, when a Canadian company employs a Canadian worker to do SR&ED - a strictly defined but wider definition than R&D - the government will pay you back somewhere around 48%-70% of the salary you paid out.

The government web site about this is a little confusing, indicating credits of more like 20%-35%, but what they don't say is that you weight wages by about 165% to include non-salary overhead for that employee. There are also province-specific parts that add to the total. The end result is much more than 20%.

Think about that. If you're a privately-held Canadian company, you can be getting back something like 70% of your R&D employee wages. It doesn't matter if you don't even turn a profit; "tax credits" means "free money," not tax writeoffs. It means that hiring Canadian developers has roughly the same cost as outsourcing development to India.

IANA (I Am Not an Accountant), please don't sue me, etc. But if you're a Canadian software company, do yourself a favour and apply for those tax credits.

2007-12-15 »

In which I learn the true meaning of "unbelievable"

It's after midnight. I arrive home in Montreal after a few weeks absence, to find the cheesy-overpriced fingerprint lock on my condo's door has been replaced with a hotel-style card reader lock.

I investigate more fully. Every lock on every door in the building has been replaced with a hotel-style card reader lock.

I have some problems with this:

  • It's not a rental. It's my @#$!#$ lock that they stole. I actually paid extra for the cheesy-overpriced fingerprint lock, which is precisely how I know it's overpriced.

  • The card reader lock does not have a keyhole nor a fingerprint reader, and I do not have a card to read.

  • In my mailbox, I find no notice whatsoever that this operation had been planned or executed.

  • The new lock is very poorly installed, in keeping with the shoddy construction work that has characterized this building all along. (Luckily, the contractor who built the place has high standards, and repeatedly sent each worker back until they did it right. So it's great work in the end. But he obviously hasn't seen this new crap yet.)

Naturally I break in (to my own home) through my other door, which has a perfectly normal easily pickable lock that completely defeats the purpose of the cheesy-overpriced lock I no longer have. I didn't have to pick it; since the last time, when my cheesy-overpriced lock decided it didn't want to let me in anymore, I make sure to carry a key for the perfectly normal lock with me at all times.

I come in.

Everything inside is normal.

It's the middle of the night.

I don't even know the superintendent's name.

I've lost his phone number.

It's time for bed now.

2007-12-19 »

On the efficiency of using auto-refactoring IDEs

    Imagine that you have a tool that lets you manage huge Tetris screens that are hundreds of stories high. In this scenario, stacking the pieces isn't a problem, so there's no need to be able to eliminate pieces. This is the cultural problem: they don't realize they're not actually playing the right game anymore. -- Steve Yegge

2007-12-21 »

Thread-free coroutines in C# 3.0

As I suspected, C# 3.0 has everything we need to accomplish a clone of WvCont from WvStreams in C++. It took a bit of fiddling to figure it out, but the final answer is simple and elegant.

The code below shows a ToAction() extension method that lets you convert any iterator into an Action, so that anywhere a "normal" callback is expected, you can provide a coroutine instead.

We do some non-obvious tricks with variable scoping in ToAction(), but that only has to be written once. The syntax for using it is simple.

using System;
using System.Collections;
using System.Linq;

public static class Example
{
    public static Action ToAction(this IEnumerable aie)
    {
    bool must_reset = false;
    IEnumerator ie = aie.GetEnumerator();
    return new Action(delegate() { 
        if (must_reset)
        ie = aie.GetEnumerator();
        must_reset = !ie.MoveNext();
    });
    }

    static IEnumerable demofunc(string prefix, int start, int end)
    {
    for (int i = start; i <= end; i++)
    {
        Console.WriteLine("{0}: {1}", prefix, i);
        yield return null;
    }
    // falling through here is like an extra yield
    }

    public static void Main()
    {
    Action a1 = demofunc(" *   ", 1, 3).ToAction();
    Action a2 = demofunc("   * ", 100, 200).ToAction();

    for (int i = 0; i < 10; i++)
    {
        a1();
        a2();
    }
    }
}

And the output looks like this:

 *   : 1
   * : 100
 *   : 2
   * : 101
 *   : 3
   * : 102
   * : 103
 *   : 1
   * : 104
 *   : 2
   * : 105
 *   : 3
   * : 106
   * : 107
 *   : 1
   * : 108
 *   : 2
   * : 109

The above program requires Mono 1.2.6 or higher (compile with "-langversion:linq") in Linux, or .NET 3.5 or higher in Windows.

November 2007
January 2008

I'm CEO at Tailscale, where we make network problems disappear.

Why would you follow me on twitter? Use RSS.

apenwarr on gmail.com