Log in

Ben's · Beta · LJ

Recent Entries · Archive · Friends · Profile

* * *
It is absolutely crazy how quick this last year has flown by. It seemed like just yesterday things were thawing out and it was time to start biking, and now here we are again. Madness. I'm starting this year off in a bit of a slump, too, which doesn't bode too terribly well. Let's see if I can't blog, code, and exercise my way out of it.
* * *

Spring is coming, and although remnants of the last major snowfall still peek out from the lawns of some shady side streets, the air is fresh and the sun is bright. Sunday mornings now have that golden sunrise hue that seems to promise to last forever. New Year's Day was back in January, but as far as I'm concerned, this is really the new beginning.

My brother Mark moved in to a new place near Bathurst and Harbord with his girlfriend. The apartment is a second story one bedroom affair above what once was a coachhouse and now stands vacant. I haven't seen the inside yet - they just moved last Monday - but the bedroom has an east facing floor to ceiling window which promises glorious mornings, hardwood floors that Mark just loves, and best of all, blissful silence: nobody in the same building at all, above, below or beside. He's looking forward to doing a lot of writing and studious movie watching. I would be lying if I said I wasn't a little envious.

Rob W,, my dear old friend, is getting married in Ottawa this next weekend to his lovely fiancée Kate E. It's that time of life when friends are starting to marry, to buy houses, start families. On the one hand, it's delightful to see everyone doing so well, and to be handed such excellent opportunities to spend time with people who have drifted away a bit after the academic crush. On the other hand, it's a sobering reminder that there is a lot of work and forethought necessary to maintain an average middle-class lifestyle, and I've been letting that slide for too long now. On the gripping hand, I'm hugely happy for Rob and Kate, and I can't wait to celebrate with them.

Yay, Spring!

Current Location:
* * *
Just like many other people, it seems that I've let twitter devour my blogging habit (if ever I really had one, that is, which is debatable). There have actually been a few times recently when I decided to not broach a particular topic because I couldn't think of a reasonable way to fit the thought into 140 characters... and frankly that's just crazy talk. I'm going to try building blogging back into my online habits, and I'm not waiting for any silly new year's resolution timing to do so. Since I spend more synchronous personal online time on my mobile these days than on my main machine, I've got to find a tool that will if not take advantage of that fact, then at least not be hobbled by it. LJ2ME is my first attempt at finding a tool for this purpose. It's pretty raw so far, but it looks like it might get the job done. My next try will probably involve figuring out how well Opera Mobile can render LJ. One way or another, though, I'm getting this thing back on track. Hello, world!
Current Location:
In bed
* * *

Executive Summary

  • Google Wave looks like a very nice concurrent rich text editor;
  • I'm worried that it is being positioned to replace tools that are far better in their niche than Wave currently is;
  • I'm worried that it may be able to replace tools that are better than Wave has the potential to be, and that it may therefore subtract [some] value from the internet as a communications medium.
Cut due to enormous volume of blatherCollapse )

Regression Bad, or, Hands Off My Email, or, Get Off My Lawn

I am very worried by Lars Rasmussen's description[8] of how he believes Wave relates to email:

Q: This seems like this will replace email - but can it really replace all we love about email?

Lars: We think of email as an incredibly successful protocol. Google Wave is our suggestion for how this could work better. You can certainly store your own copy by way of the APIs and with the extensions. The model for ownership - it's a shared object, so how do you delete the object? Even though it's a shared object, no one can take it away from you without your consent. There will eventually be reversion to sync up with the cloud or you own servers. We're not planning on having spam in wave (laughs). Early on in email, spam wasn't really taken into account, so we benefit from that learning experience. We're planning on a feature so that you can't add me to your Wave without being on a white list.

Later on, Lars mentions that a bidirectional email-to-wave gateway might be difficult, but possible. The problem is that email includes a set of well-structured header information and the optional ability to include an arbitrary number of body elements, each which may contain highly structured information (e.g. MIME sections containing binary files), semistructured documents (e.g. HTML, Markdown, format=flowed, or other text formats which offer hints about enhanced rendering while not requiring it) or unstructured text; whereas Waves appear to not only strip away the requirement for this extra richness but also the ability to include it.

Accepting and rendering down rich structure while offering only text with primarily presentational markup makes for a unbalanced flow of information.


  1. @rcwoolley, personal correspondence
  2. http://www.youtube.com/watch?v=v_UyVmITiYQ
  3. http://www.youtube.com/watch?v=Sx3Fpw0XCXk
  4. http://www.waveprotocol.org/whitepapers/internal-client-server-protocol
  5. http://www.waveprotocol.org/whitepapers/operational-transform
  6. http://www.maetico.com/everything-and-wave/
  7. http://www.techcrunch.com/2009/05/28/google-wave-drips-with-ambition-can-it-fulfill-googles-grand-web-vision/
  8. http://www.techcrunch.com/2009/05/28/live-with-the-google-wave-creators/
  9. http://www.texttechnologies.com/2009/05/29/google-wave-finally-a-microsoft-killer/
  10. http://twitter.com/gnomon/status/2011194686
* * *

Passion radiates. You can see it roll off people in waves, like haze from a locomotive engine. Like that heat, passion doesn't do much in a vacuum, and most of it gets wasted as entropy.

Manage it properly, though, and heat becomes flame, flame becomes fire. Fire can warm the needy, lift rockets to the heavens, and light the way through temples, tombs and libraries.

Fire brings light. Cast wide, it can bring knowledge and safety; focused coherently, in can carry words and thoughts to the other side of the world, or on into the far future.

Passion - gathered, directed, encoded - powers the world.

My passion is for the written word. I use it awkwardly, but I love it dearly. Thought, inspiration, hard-fought wisdom and brilliant insight live on and leap from person to person, across generations, as simple words. Used well, words uplift and ennoble us. They are the crowning achievement of humanity.

That gleaming potential is all too often tarnished by poor use. Bad language is wasteful and frustrating, like a stubborn sneeze or an unreachable itch. It can be mundane; it can be tragic. And it can be avoided.

Every word is an opportunity to do well, and to do good; to strike a chord and hear it richly resonate; to drop a stone in a pond and watch the ripples spread. Every word is a chance to stoke the embers of our passions and pass on a little warmth.

We can all choose to have our words be slow and calm; fierce and torrential; strong and bright and beautiful.

We can all do better.

We can all do better.

* * *
* * *

Optical fiber is a brilliant invention: it is a thread of spun glass. By the magic of total internal reflection, the refraction index of the material, and the wavelength(s) of the light fired down the pipe; by the engineering of dense wavelength multiplexing, and quantum-tunneling solid-state laser boosters set into the fiber every few kilometers; and, sometimes, by the hard work of cable-laying ship captains who stubbornly brave the high seas to thread this spun glass across the ocean floor, billions of bits flow from point to point across the world. Against all odds, not to mention the second law of thermodynamics, the world has managed to hew from the static of random potential the most powerful communications tool our civilization has ever seen.

Now. I don't like TV.

This Christmas I was given a generous gift: a Hauppauge HVR-950 USB TV tuner. I really, really wanted one of these. The widget is about the size of one of those slim Zippo lighters. I plug one end in to my USB hub and the other end to a coaxial cable that runs to a telescoping antenna of the same sort you'd find on a plastic radio. With the help of twelve kilobytes of closed-source firmware dynamically loaded into its onboard processor, I can tune into a whole set of channels streaming right out of the CN tower, not to mention what comes across the water from Buffalo. The CBC broadcasts an MPEG-2 stream with 1920 by 1080 lines of interlaced resolution; mplayer gives me a variety of options to upsample the spatial resolution with the help of the extra temporal resolution added by the interlacing of the fields.

The video stream is completely independent of the transmission technique, and my bargain-priced, extremely powerful quad-core processor makes short work of the digital signal; but the HVR-950 itself does some fascinating, insightful and difficult work to condense the vapour of that feeble radio transmission into something from which the video signal can be recovered.

The little widget gets warm when it's in use. The signal varies depending on what lies between the antenna and the window.

We have covered the planet with a web of spun glass and the dreams of a world light the fiber day and night; but that pride is completely different from the flare of inspiration sparked by the faintest of radio signals, coming through thin air from the other end of the world.

* * *

Dear LJ,


  • an explanation of why I recently bought an Intel D945GCLF Atom motherboard (short story: my laptop died spectacularly, G45-based motherboards won't hit retail channels for another two months, I can't wait that long for a new system, and I wanted a low-power standalone file server anyhow);
  • an explanation, and perhaps explanatory pictures, of why the abovementioned motherboard is currently housed in a cardboard box tied with pink wrapping ribbon;
  • how-to documents detailing how to get Damn Small Linux 4.4.2 playing nicely with..:
    1. a D-Link DGE-530T gigabit PCI network card (PCI ID 1186:4b01, rev 11);
    2. the built-in RealTek RTL8102E 10/100 network chip (PCI ID 10ec:8136, rev 02);
    3. the 82801G audio controller built into the ICH7 north bridge (PCI ID 8086:27d8, rev 01);
    4. Firefox 3;
  • news about my recent awk hackery;
  • an update on the job search.
Current Mood:
* * *
From: "Ministers Prentice and Verner" <Minister.Industry@ic.gc.ca>
To: CanadianCitizens@everywhere.com
Subject: An Act to Amend the Copyright Act
Date: Thu, 12 Jun 2008 13:09:06 -0400

The Government of Canada has introduced Bill C-61, An Act to Amend the Copyright Act. The proposed legislation is a made-in-Canada approach that balances the needs of Canadian consumers and copyright owners, promoting culture, innovation and competition in the digital age.

We've introduced our version of Bill C-60. We removed a bunch of the exceptions that protected consumers from legal harassment, added in a couple of media attention grabs, and made it illegal to share or even talk about the tools that would allow anyone to take advantage of the exceptions that we did leave in.

We wrote it on Canadian soil, so we qualify for the sticker.

We totally caved to the US IP lobby, and we even borrowed wording from the WIPO treaty, but this is good for Canadians! It means that more money will be invested into our knowledge economy!

What does Bill C-61 mean to Canadians?

Quit screaming at us! We're just doing a favour to some people that asked really, really nicely. And they really, really want what we're giving them, so that makes everything OK.

Specifically, it includes measures that would:

  • expressly allow you to record TV shows for later viewing; copy legally purchased music onto other devices, such as MP3 players or cell phones; make back-up copies of legally purchased books, newspapers, videocassettes and photographs onto devices you own; and limit the "statutory damages" a court could award for all private use copyright infringements;

You can do everything that you've been doing up until the mid-90s, but you can't back up your DVDs, video games or application software. Also, you're not allowed to back up anything that has any kind of DRM on it, because permitting circumvention for legal uses makes IP owners mad. You're just not allowed to break DRM, mmmkay? Unless you're a security researcher, because then you're doing it for educational purposes.

Who qualifies as a security researcher? We'll let case law figure that out! That's what it does best.

If you download music onto digital media that you've purchased, you've already payed a significant levy that filters back to the organization that represents Canadian musicians. The 2004 Finckenstein decision in BMG Canada Inc. v. John Doe may have said that paying the levy means you're allowed to download music, but we only want you to pay attention to Sexton's assertion that Finckenstein shouldn't have explicitly said that downloading music was legal.

So we're still charging you extra for the media you buy, because the CRIA lobbied good and hard through the 80s and 90s for it, but now we're making it illegal for that surcharge to actually give you any value.

We're limiting the damages to five hundred bucks per song that you download. That's just plain reasonable, of course: if you've downloaded a song, there isn't any reason for you to buy the twenty copies of the CD that you normally would have, and it's only fair to make sure that music publishers get the money they're owed. If you're uploading, though, god help you, because there aren't any limits on the damages there.

We understand what "peer-to-peer" means, but we hope that the news media doesn't, so they'll glom onto the 500 number and conveniently ignore that there's no protection here at all.

  • implement new rights and protections for copyright holders, tailored to the Internet, to encourage participation in the online economy, as well as stronger legal remedies to address Internet piracy;

We think the internet makes the marketplace difficult for companies that have a lot of money but no real idea how to compete in it. We're going to make it easy for old companies to litigate these new upstarts right out of business. They have less money, so they can't lobby as well; they can't afford as many lawyers, so we'll set a bunch of precedents that continue to reinforce aging and ailing business practices; and everyone will be happy, happy, happy!

We'll ignore the complexities of transparent redistribution, copying-vs-caching, remixing and open licenses, because those things are new and hard to understand. We'll let case law waltz through that minefield. That worked great for Australia and the US!

  • clarify the roles and responsibilities of Internet Service Providers related to the copyright content flowing over their network facilities; and

We don't want to require Canadian internet service providers to police the content that flows through their networks because Canada actually has a Privacy Commissioner. We would be hung by our eyelids and kicked until we blink. That's, um, bad for Canadians. And the marketplace. And innovation. And we like our eyelids.

We'll require ISPs to forward takedown notices to customers instead of requiring them to immediately remove the material. This may seem a little soft on violators, sure, but we still don't impose any penalties on companies that issue incorrect notices. Scattershot subpoenas and intimidation are still valid tactics!

  • provide photographers with the same rights as other creators.

Oh, and we'll throw a sop to the photographers. They've been getting boned for decades. Time to bone some other group for a while.

What Bill C-61 does not do:

  • it would not empower border agents to seize your iPod or laptop at border crossings, contrary to recent public speculation

Bill C-61 doesn't let border guards seize your digital devices, because bills are subject to parliamentary review. Instead, we'll leave that to the ACTA, which we're working on in secret. Canadians don't have to worry their pretty little heads about the international commitments that we're making on their behalf. Nobody will mind, anyhow: border crossing is such a fast, painless procedure that adding on just a little bit of intrusive searching won't hurt anyone.

What this Bill is not:

  • it is not a mirror image of U.S. copyright laws. Our Bill is made-in-Canada with different exceptions for educators, consumers and others and brings us into line with more than 60 countries including Japan, France, Germany and Australia

We are high as kites.

Bill C-61 was introduced in the Commons on June 12, 2008 by Industry Minister Jim Prentice and Heritage Minister Josée Verner.

We made this! Right here in Canada! That makes it good!

For more information, please visit the Copyright Reform Process website at www.ic.gc.ca/epic/site/crp-prda.nsf/en/home

Thank you for sharing your views on this important matter.

Our circular file welcomes your feedback.

The Honourable Jim Prentice, P.C., Q.C., M.P.
Minister of Industry

The Honourable Josée Verner, P.C., M.P.
Minister of Canadian Heritage, Status of Women and Official Languages and Minister for La Francophonie

Current Mood:
disappointed disappointed
* * *

Because my cow-orkers just had to bring up the Dreaded Site™, and I just had to look at the Scheme version and note that, while at least it was present, the organization of the code in all three versions left a great deal to be desired. A few more moments of reading revealed that the output was wrong, too.

I'm sure you can see where this is going.

;; Gnomon - on Thu Apr 17 23:54:52 EDT 2008
;; sha1sum of lastname, firstname, newline:
;; 3952893c66ffbe071f266caa04b25161c1da30a1
;; Because I wanted a version that would Do
;; The Right Thing with capitals and plural
;; cases, and because mixing logic, display
;; and generation code does not satisfy me.

(define (iota n)
  (let loop ((l '()) (i 0))
    (if (> i n)
        (loop (cons i l) (+ i 1)))))
;; See SRFI-1 for a better version of this;
;; my function is backward in several ways.
;; It can also be argued that SRFI-42 could
;; allow an implementation that consed up a
;; bit less temporary garbage. If SRFI-1 is
;; out, though, SRFI-42 is way out. Basics.

(define (plural? n . up)
  (let ((.. string-append)
        (num (number->string n))
        (bot " bottle")
        (ltr (if (null? up) "n" "N")))
    (case n ((0) (.. ltr "o more" bot "s"))
            ((1) (.. num bot))
            (else (.. num bot "s")))))
;; PLURAL? has to merge the logic for cases
;; when the string will be used at the head
;; of a sentence, requiring a capital; when
;; only one bottle is left, which needs the
;; singular form; and when none are left at
;; all, which requires a special case. It's
;; lucky that not all combinations of these
;; cases can be reached, allowing us to use
;; only three of the possible six branches.

(define (verse n)
  (let ((.. string-append)
        (top (plural? n 1))
        (mid (plural? n))
        (nxt (plural? (if (= n 0)
                          (- n 1))))
        (beer " of beer")
        (wall " on the wall")
        (actn (if (= n 0)
                  "Go to the store and buy some more, "
                  "Take one down and pass it around, ")))
    `(,(.. top beer wall ", " mid beer ".")
       .  ,(.. actn nxt  beer wall "."))))
;; VERSE conses a pair where the CAR stores
;; the first line of the verse, and the CDR
;; the second. There is no sense in using a
;; proper list; we would just waste the end
;; of it anyways. Also: yay quasiquotation!

(define (sing verse)
  (let ((n newline))
    (display (car verse)) (n)
    (display (cdr verse)) (n) (n)))
;; SING exploits the implicit BEGIN wrapped
;; around the body of a LET to DISPLAY both
;; lines of a verse in order. Also note the
;; pleasant symmetry of CAR and CDR that we
;; get to use because of our choice made up
;; above in VERSE to use a dotted pair as a
;; representation instead of a proper list.

(for-each sing (map verse (iota 99)))
;; MAP for effect, FOR-EACH for side effect

It's been submitted for inclusion, of course, with the following lines as an additional note to the site maintainers:

;; The code is long, the comments too;
;; A bit less wrong than version two;
;; No syntax-case, like version three;
;; Just one right place per step, you see.

I'm a little bit in love with the A+ version.

Current Mood:
tired tired
* * *

I'm going to start posting the random bits of awk code that I come up with.


For a project about which I'll be writing more in a bit, I needed the ability to quickly produce long strings - on the order of a few dozen, and in some case a few hundred, mebibytes. I went through several iterations before I came up with a version that I liked. That version is called rep6 in the below source code; in my personal library file I would just call it rep.

#!/bin/gawk -f 

# by gnomon
# sha1sum of printf "%s %s", firstname, lastname:
# 1110be40263bc427f7906f4e01c0cc218c6daf6e
# Tue Apr  8 21:11:32 EDT 2008
# posted to #awk in the hopes of garnering some feedback
# about style, ideas and performance. 

# GPL v2 (but it's not finished yet, so why bother?)

function rep1(s,n,      r) {
# O(n) allocate/appends
# 2 lines of code
# This is the simplest possible solution that will work:
# just repeatedly append the input string onto the value
# that will be passed back, decrementing the input count
# until it reaches zero.
        while (n-->0) r = r s;
        return r;

function rep2(s,n,      r) {
# O(1) + O(n) allocate/appends
# 3 lines of code
# The idea here is to generate a string of length n with
# sprintf and then use gsub to replace everything in the
# generated string with the input string. Hopefully this
# will take advantage of some smart internal workings of
# the regex engine to avoid repeated allocations.
# UPDATE: false hope. This is by far the slowest tactic.
        r = sprintf(("%0"n-1"s"),"0");
        return r;

function rep3(s,n,      c,n2,r,r2) {
# O(log n) allocate/appends UPDATE: this is a lie!
# 6 lines of code
# Here we trade for faster execution by sacrificing some
# code clarity. We keep a temporary string and a counter
# that we start off at 1, doubling both until we pass n;
# then we start over at 1, and we repeat until exactly n
# is reached. This may be ugly but it is faaaaaaast.
        for (;c < n; c += n2) {
                r2 = s;
                #for (n2=1; n2*2<(n-c); n2*=2) {
                #     APPEND++; r2=r2 r2}
                for (n2=1; n2*2<(n-c); n2*=2) r2=r2 r2;
                # APPEND++;
                r  = r r2;
        return r;

function rep4(s,n) {
# O(1) allocate/appends
# 2 lines of code
# A feat - both stupid and naive! Is consing up a string
# to avoid repeated print operations really that bad, or
# can good buffering make a dumb idea actually workable?
# UPDATE: no, it can't. This still handily beats out the
# gsub version, but it's slower than rep1 and way slower
# than rep3. Moral: buffer not the unbufferable!
        while (n-->0) printf s;
        print "";

function rep5(s,n,      r,x) {
# O(log n) allocate/appends - *actually true* this time!
# 3 lines of code
# Rather than keeping track of a counter like rep3 does,
# here we just use the call stack and recurse. Turns out
# that I run out of RAM way faster than gawk runs out of
# call stack. There may be a good threshold at which the
# recursion can halt and we fall back to a simple append
# approach like rep1 - but really, why bother? This code
# is simple and fast. Also, the shortest possible string
# is one character, and 32 recursive calls turn that one
# character into 4,294,967,296; that is more than enough
# to fill all available RAM on most current machines. If
# it doesn't, the performance is likely to be limited by
# the speed of malloc() (and therefore sbrk()) anyhow. A
# quick test reveals that gawk 3.1.5 on a 32-bit x86 box
# with 512 megs of RAM can stack just short of 7e3 calls
# before segfaulting; dc -e'2 7000^f' prints a very long
# number indeed: 2108 decimal digits, to be precise, and
# it will presumably take a good long while before every
# normal machine has that many bytes of RAM. We're safe.
        if (n < 2) x = (n == 1);
        else r = rep5(s,(n-(x=(n%2==1)))/2);
        return (r r (x?s:""));

function rep6(str,num,  remain,result) {
# O(log n) allocate/appends - identical to rep5
# 7 lines of code
# This is a much cleaner version of the preceding block.
# For some reason I enjoy reading awk code bereft of the
# optional semicolons, but I enjoy writing it with; this
# is odd, but there it is. It'd be less embarassing if I
# showed only the below without any of the above, but it
# would be less valuable and less honest.
        #DEPTH++; # global var for counting recursions
        if (num < 2) {
                remain = (num == 1)
        } else {
                remain = (num % 2 == 1)
                result = rep6(str, (num - remain) / 2)
        return result result (remain ? str : "")

        #NUM = 10000000;     STR = "foo";
        NUM  = ARGV[1] + 0; STR = ARGV[2];
        delete ARGV[1];    delete ARGV[2];
        if        (ARGV[3] ~ /0/) {
                exit 0;
        } else if (ARGV[3] ~ /1/) {
                print rep1(STR,NUM);
        } else if (ARGV[3] ~ /2/) {
                print rep2(STR,NUM);
        } else if (ARGV[3] ~ /3/) {
                print rep3(STR,NUM);
                #print APPEND >> "/dev/stderr";
        } else if (ARGV[3] ~ /4/) {
        } else if (ARGV[3] ~ /5/) {
                print rep5(STR,NUM);
                #print DEPTH >> "/dev/stderr";
        } else if (ARGV[3] ~ /6/) {
                print rep6(STR,NUM);
                #print DEPTH >> "/dev/stderr";
        delete ARGV[3];
        exit 0;

# - investigate whether some tactics work better when
#   consing small iterations of very large strings;
# * done: the version that starts at one, doubles until
#   overflow and then starts again at one
# - see if there's some way of making the gsub approach
#   work better: it's too fun to abandon outright;
# - is there some way to use fewer state variables in
#   rep3? The current version is really awkward;
# - is there any way to collapse or compound the r2 and
#   r assignments in rep3 to shave a line or two?
# * sure, but rep3 is a dead end anyway. Reusing the
#   value returned by a variable assignment to remove a
#   reference to it works, as in rep5, but the result
#   is a mess and a waste of effort. Still fun, though.
Current Mood:
tired tired
Current Music:
Postmaster, from Demographically Unsound by Tettix
* * *
* * *