Sand two glosses

Ewe bed err war shout
Ewe bed err knock rye
Ewe bed err notch out
I’m telling you eye
Sand two glosses car mint to town

He’s may king’ll list
Shaking it wise
Khan a fine tout who’s
Gnaw tea and ice
Sand two glosses car mint to town

He seize hue in yours leaping
He no swan euro ache
He no sieve you’ve bin batter could
Soapy good fur could nose ache

Ewe bed err war shout
Ewe bed err knock rye
Ewe bed err notch out
I’m telling you eye
Sand two glosses car mint to town

(Previously.)

Santa is dead. Long live Santa.

My kids know the truth about Santa Claus. Do you?

It happened on my birthday, of all days, a year ago. The boys were seven-and-a-half and nine-and-a-half. For a few months prior, whenever Santa Claus came up in conversation, whichever boy was speaking would cast me or my wife a sidelong glance and say pointedly, “a.k.a. Mom and Dad!” and the conversation would continue without further comment. So the bubble had already burst, they just lacked official confirmation — which notably they didn’t explicitly seek until we were sitting all together in the living room, getting ready to watch my birthday movie selection. When they did, I asked if they really wanted to know the truth. Archer, who is younger, just barely did, in my judgment. Jonah was burning for it.

So I opened the Wikipedia page about the real St. Nicholas and talked about him for a bit, and how he became renowned as a gift-giver. He was an ordinary man, so of course he died; but the gift-giving idea lived on.

Today, around Christmas every year, the spirit of St. Nicholas takes hold of parents everywhere. So although there’s no guy with a magical sleigh, and other parts of the story certainly are made up, still, in a very real way — and I told them this is honestly exactly what I believe — there is a Santa Claus, and Santa Claus is the idea of giving, and he/it really does travel around the whole world in a single night! He just needs us parents to do his work for him. You’ve heard of Santa’s elves? We’re it.

The boys seemed pretty happy with this explanation. Jonah, for his part, was happy merely to have Santa Claus officially debunked. I repeated my point about the reality of Santa Claus, and Archer said, “I half-believe you and I half-believe Jonah.” “Making up your own mind. I love that,” I told him.

Soon after that we let the boys see Batman Begins, despite some concerns about age-appropriateness. There’s the scene where Bruce Wayne decides he has to have a costumed alter ego:

“As a man, I’m flesh and blood. I can be ignored. I can be destroyed. But as a symbol? As a symbol I can be incorruptible. I can be everlasting.” The point being that if Bruce Wayne is ever injured or killed (or grows too old, which is the premise of Batman Beyond), someone else can don the suit and take over as Batman. In a way this is exactly what happened with St. Nicholas — the Bruce Wayne of gift-giving. Now that was a Santa explanation the kids could relate to.

How (and why) to program, part 2

This entry is part 2 of 2 in the series How (and why) to program

It’s National Computer Science Education Week! That must mean it’s time for part 2 of my How (And Why) To Program series. Today I will discuss a tricky but powerful concept in computer science: recursion.

Briefly, recursion means accomplishing a task by performing it in terms of smaller versions of the same task. For example, each morning I execute my “drive to work” routine, which is really my “drive from point A to point B” routine, where point A is home and point B is work. To do that, I first do “drive from point A to point B” where point A is home and point B is the Golden Gate Bridge (which is about halfway to work for me), followed by “drive from point A to point B” where point A is now the Golden Gate Bridge and point B is work. Each of those steps, of course, can be decomposed into smaller “drive from point A to point B” tasks.

One classic example for illustrating recursion in computer code is the Fibonacci sequence — the mathematical sequence in which each number is the sum of the two before it. You might already see the weakness in that definition: what can the first and second numbers in the sequence be, if they don’t have two numbers before them that can be added together? This is a key feature of recursive functions: at some point they reduce the problem into parts so small that they reach the “base case,” where the recursive rule breaks down. It happens that the base case of the Fibonacci sequence says the first two numbers are 0 and 1. From there, the recursive rule takes over to give the numbers that follow: 1, 2, 3, 5, 8, 13, 21, 34, and so on.

Let’s look at a “function,” which is the computer programming equivalent of a recipe: you give it some inputs, and it gives you an output, the result of processing the inputs in specific ways. Our function is called fibonacci and it takes one input, or “argument”: a number, which we’ll call n. The result of fibonacci(n) will be the nth number in the Fibonacci sequence, where the first two numbers — fibonacci(0) and fibonacci(1) (recall that in programming, lists and sequences of things are almost always numbered beginning at zero) — are 0 and 1.

As before, code samples are presented in the Python programming language, though the same concepts we’re discussing apply to most other programming languages too.

def fibonacci(n):
  if n == 0 or n == 1:
    return n
  else:
    return fibonacci(n-1) + fibonacci(n-2)

We start with “def fibonacci(n),” which simply means “define a function named fibonacci taking one argument called n.” The body of the function follows. First it checks for the base case: does the caller (whoever is invoking this function) want one of the first two Fibonacci numbers? If so, the function simply “returns” (or hands back to the caller) the value of n, since by coincidence the value of fibonacci(n) is n when n is 0 or 1.

If it’s not the base case, the function returns a different value: the sum of invoking fibonacci first on n-1 and then on n-2. Those recursive calls give the two prior Fibonacci numbers. For instance, if we invoke fibonacci(9), then n is 9 and fibonacci(n-1) is fibonacci(8), which is 21; and fibonacci(n-2) is fibonacci(7), which is 13. Adding those together gives 34, which is the correct result for fibonacci(9).

Enough about the Fibonacci sequence. It’s a contrived example and, though it explains recursion pretty well, it doesn’t demonstrate the real-world applicability of the technique. (It also happens that, for reasons I won’t go into here, recursion is a terribly inefficient way to compute Fibonacci numbers compared to other possibilities like iteration.)

A few days ago, my Mensa Puzzle-a-Day Calendar presented this riddle:

The letters of a certain three-letter word can be added in sequential order (though not necessarily with all three letters together in the same place) to each of the letter strings below to form common, uncapitalized English words. You don’t need to rearrange any of the letters below. Simply add the three needed letters in sequential order. What is the three-letter word, and what are the nine new words formed?

1. alp 2. wl 3. marit 4. ealus 5. urneman 6. cke 7. disintedl 8. traectr 9. epard

(To illustrate the puzzle: the letters of what three-letter word can be inserted in both “hoyde” and “ckear” to produce common English words? The answer is “new,” to produce “honeydew” and “neckwear.”)

Staring at the puzzle for a while, I was unable to solve it. So I sat down and wrote a program to solve it for me. How’s that for real-world applicability?

Once again I relied on the file /usr/share/dict/words (or sometimes /usr/dict/words, or /usr/lib/dict/words) that is a standard feature of some operating systems; it’s simply a list of many common English words (and many uncommon ones, plus some frankly questionable ones), one per line. Reading that file, I produced two sets of words: one set of all the words, and one set of all three-letter words. Here’s how that looks:

three_letter_words = set()
all_words = set()
wordlist = open('/usr/share/dict/words')
for word in wordlist:
  word = word[:-1]
  all_words.add(word)
  if len(word) == 3:
    three_letter_words.add(word)
wordlist.close()

(Very similar code is explained in detail in part 1 of this series.)

With those two word sets in hand, and the nine letter-strings from the puzzle, this was my strategy: try all possible ways of inserting the letters of all the three-letter words in each of the letter-strings. For any three-letter word, if none of its combinations with a given letter-string produces a valid word, remove the three-letter word from further consideration. In other words, beginning with all possible three-letter words, we whittle them away as they become disqualified. In the end, the only three-letter words left should be ones that combine, one way or another, with all of the nine letter-strings to produce valid words.

So, for example, the three-letter words “see” and “era” both can be added to the letter-string “alp” to produce valid words (“asleep” and “earlap”). But the three-letter word “new” can’t be, so after running through all the three-letter words on the letter-string “alp,” “see” and “era” will still be in the set three_letter_words, but “new” won’t be.

Here’s how that strategy looks:

for string in ("alp", "wl", "marit", "ealus",
               "urneman", "cke", "disintedl",
               "traectr", "epard"):

This starts a loop that will run nine times, once for each letter-string, giving each letter-string the name “string” on its turn through the body of the loop.

  three_letter_words_to_discard = list()

This creates an empty list called three_letter_words_to_discard. It’s empty now but as we progress we will fill it with words to remove from the three_letter_words set.

(If you’re wondering why I sometimes use lists for collections of things, and sometimes use sets, gold star! The answer is that they are two different kinds of data structure, each one good at some things and bad at others. A set is very fast at telling you whether a certain item is in it or not; a list is slow at that. On the other hand, a list keeps things in the same order in which you added them; a set doesn’t do that at all.)

  for three_letter_word in three_letter_words:

This starts a nested loop. It’ll run through the complete list of three_letter_words each of the nine times that the outer loop runs.

    combinations = combine(three_letter_word, string)

Here we presume there’s a function called combine that takes the current three-letter word and the current letter string, and produces the complete list of ways that the letters of three_letter_word can be interspersed with the letters of string. For example, combine(“abc”, “def”) should produce the list [“abcdef”, “abdcef”, “abdecf”, “abdefc”, “adbcef”, “adbecf”, “adbefc”, “adebcf”, “adebfc”, “adefbc”, “dabcef”, “dabecf”, “dabefc”, “daebcf”, “daebfc”, “daefbc”, “deabcf”, “deabfc”, “deafbc”, “defabc”]. That’s where recursion is going to come into play. We’ll get to writing the combine function in a moment.

    good_combinations = list()
    for combination in combinations:
      if combination in all_words:
        good_combinations.append(combination)

With the list of combinations in hand, we now look through them to see which of them are valid words, if any. We set good_combinations to be a new empty list where we’ll accumulate the valid words we find. We loop through the combinations, testing each one to see if it’s a member of the set all_words. If one is, we add it to the list good_combinations.

    if good_combinations:
      print three_letter_word, "+", string, "=", good_combinations
    else:
      three_letter_words_to_discard.append(three_letter_word)

After the “for combination in combinations” loop, we check to see whether good_combinations has anything in it. (“If good_combinations” is true if the list has something in it, and false otherwise.) If it does, we print out the current three-letter word, the current letter-string, and the list of valid words they make. If it doesn’t, then three_letter_word goes into our list of three-letter words to discard.

  for word in three_letter_words_to_discard:
    three_letter_words.remove(word)

After the “for three_letter_word in three_letter_words” loop, this small loop does the discarding of disqualified three-letter words.

Why not simply discard those words from three_letter_words in the preceding loop, as we run across them? Why save them up to remove them later? The answer is that when you’re looping through the contents of a data structure, it’s a bad idea to add to or remove from the data structure. The loop can get confused and lose its place in the structure. It may end up running twice with the same list member, or skip a member entirely. It’s safe to make changes to the membership of the data structure only after the loop finishes.

Finally, after the outermost loop has finished, it’s time to see which three-letter words remain in our set:

print three_letter_words

And that’s all! All except the tricky part: the combine function. Here is how it starts:

def combine(string1, string2):

It takes two strings. We’ll give them generic names, string1 and string2, so as not to assume that either one is a three-letter word. As you’ll see, often neither one is.

Now, how to approach writing a recursive function? It’s usually a safe bet to start with the base case, the conditions under which combine isn’t recursive. The recursive step will involve passing shorter and shorter strings to combine, so the base case is when one or both of the strings is empty. Obviously if either string is empty, the result should be the other string — or more precisely, the list containing the other string as its one member (since we’ve already stipulated that the result of combine is a list of strings). In other words, combine(“”, “def”) should produce the list [“def”] — which after all is the result of interspersing the letters of “” among the letters of “def” — and combine(“abc”, “”) should produce [“abc”].

So here’s the body of combine so far. It’s just the base case:

  if len(string1) == 0:
    return [string2]
  elif len(string2) == 0:
    return [string1]

(Recall that “elif” is Python’s abbreviation for “else if.”)

Now for the case where string1 and string2 are both non-empty; the recursive case. The key to writing the recursive step of a function like this is figuring out (a) how to make the problem the same but smaller, and then (b) what to do with the result of computing the smaller solution.

One way to make the problem smaller is to lop off the first letter of string1. So if combine were originally invoked with the strings “abc” and “def,” the recursive call would invoke it with “bc” and “def.” Presuming combine works correctly — which is the counterintuitive assumption you must always make about the recursive step in a function like this — we’ll get back the list [“bcdef”, “bdcef”, “bdecf”, “bdefc”, “dbcef”, “dbecf”, “dbefc”, “debcf”, “debfc”, “defbc”]. None of those belongs in the result list of combine(“abc”, “def”); but if we now restore to the beginning of each of those strings the same letter we lopped off, we get [“abcdef”, “abdcef”, “abdecf”, “abdefc”, “adbcef”, “adbecf”, “adbefc”, “adebcf”, “adebfc”, “adefbc”]. This is halfway to the complete answer: it’s all the strings in the result list that begin with the first letter of string1. We only need to add all the strings in the result list that begin with the first letter of string2, and we’re done. We do this by treating string2 the same way we just treated string1: we lop off its first letter in another recursive call to combine, then paste it back on to each string in the result. Continuing the example, this means calling combine(“abc”, “ef”), which produces [“abcef”, “abecf”, “abefc”, “aebcf”, “aebfc”, “aefbc”, “eabcf”, “eabfc”, “eafbc”, “efabc”]. Sticking the “d” back onto the beginning of each of those strings gives [“dabcef”, “dabecf”, “dabefc”, “daebcf”, “daebfc”, “daefbc”, “deabcf”, “deabfc”, “deafbc”, “defabc”], and adding this list to the list from the first recursive call gives the complete solution.

In Python, the first letter of string is denoted string[0]. The rest of string, without its first letter, is denoted string[1:]. So here’s the complete version of combine, with the (double) recursive step added in.

def combine(string1, string2):
  if len(string1) == 0:
    return [string2]
  elif len(string2) == 0:
    return [string1]
  else:
    recursive_result1 = combine(string1[1:], string2)
    recursive_result2 = combine(string1, string2[1:])
    result = []
    for string in recursive_result1:
      result.append(string1[0] + string)
    for string in recursive_result2:
      result.append(string2[0] + string)
    return result

This is the crazy magic of recursion: at each step, you simply assume the next-smaller step is going to work and give you the result you need. All you have to get right is the base case and the way to process the recursive result, and — well, look:

hol + alp = ['alphol']
has + alp = ['alphas']
sae + alp = ['salpae']
her + alp = ['halper']
see + alp = ['asleep']
eta + alp = ['aletap']
era + alp = ['earlap']
soe + alp = ['aslope']
yin + alp = ['alypin']
pus + alp = ['palpus']
een + alp = ['alpeen']
kas + alp = ['kalpas']
ecu + alp = ['alecup']
ist + alp = ['alpist']
doh + alp = ['adolph']
pal + alp = ['palpal']
cul + alp = ['calpul']
ped + alp = ['palped']
Moe + alp = ['Malope']
clo + alp = ['callop', 'callop']
gos + alp = ['galops']
tid + alp = ['talpid']
yum + alp = ['alypum']
pon + alp = ['palpon']
hin + alp = ['alphin']
joy + alp = ['jalopy']
hol + wl = ['wholl', 'wholl']
sae + wl = ['swale']
soe + wl = ['sowel', 'sowle']
joy + wl = ['jowly']
joy + marit = ['majority']
joy + ealus = ['jealousy']
joy + urneman = ['journeyman']
joy + cke = ['jockey']
joy + disintedl = ['disjointedly']
joy + traectr = ['trajectory']
joy + epard = ['jeopardy']
set(['joy'])

PayPal arbitration opt-out

Bob Glickstein
[address]
[phone number]
[e-mail address]
13 Oct 2012

PayPal, Inc.
Attn: Litigation Department
2211 North First Street
San Jose, CA 95131

To whom it may concern,

I am a PayPal user at the e-mail address above. I do not agree to the Agreement to Arbitrate as delineated in your Amendment to the PayPal User Agreement and Privacy Policy dated Nov 1st, 2012. By this letter I hereby reject it per the opt-out procedure described in section 14.3 (e). Kindly exclude me from the Agreement to Arbitrate.

I further request that you consider dropping the arbitration clause altogether, for all your customers, as a matter of principle. Hand-wringing about frivolous lawsuits notwithstanding, citizen access to the public court system is one of the things that makes America great. I invite you to read my fuller thoughts on the matter at www.geebobg.com/2008/09/20/the-sue-s-of-a/

Timely written acknowledgment of this request sent to the above address would be greatly appreciated.

Sincerely,

[signature]

Bob Glickstein


Where were you in ’62?

Happy birthday to Beatlemania! The Beatles’ first single, “Love Me Do,” was released on this date fifty years ago. And happy birthday to James Bond! Dr. No, the first movie in the world’s longest-running film franchise, also opened today, also in 1962.

Earlier this year we observed the fiftieth anniversary of John Glenn’s historic orbit of the Earth, and the fiftieth anniversary of Kennedy’s landmark “we choose to go to the moon” speech.

In 1962, Stan Lee and the other adolescents at Marvel (I use the term affectionately) created Spider-Man, Thor, and the Hulk. Fifty years later, those creations are still relevant enough to star in their own brand-new blockbuster films.

The films Lawrence of Arabia, To Kill a Mockingbird, and The Music Man are fifty years old too. The famous escape from Alcatraz happened fifty years ago. The Seattle Space Needle opened to the public. Polaroid introduced its instant color film. Rachel Carson published her world-changing book, Silent Spring.

I don’t recall celebrating so many fiftieth anniversaries last year, do you? Something about 1962 appears to have been so special that we are still celebrating its achievements and events.

It wasn’t all good. People everywhere braced for global annihilation during the Cuban Missile Crisis, fifty years ago this month. Marilyn Monroe OD’d. But there was enough nostalgia for 1962 that, years later, George Lucas set the events of American Graffiti in that year, and it’s also when the action in Animal House takes place.

What was it about 1962? Fifty years from now, what events or achievements of today will people still be celebrating?

The arrow that springs from the bow

In 1996, some friends and I started our own software company, Zanshin. But by 1999, suffering from a lack of focus and a tendency toward overengineering, we had still not managed to produce a salable version of our world-changing software. Luckily for us we got a consulting gig for Amazon.com (unrelated to my involvement with the Internet Movie Database). That contract went so well that after a few months of it, in early 2000, Amazon offered to hire us all. We would have to close Zanshin and move up to Seattle. Andrea and I, newly married, got as far as scoping out Seattle neighborhoods. We were leaning toward accepting Amazon’s offer. Zanshin clearly was going nowhere, and Amazon had interesting work for us.

We had a Zanshin company meeting to talk it over. Some of us wanted to accept, some wanted to keep trying with Zanshin. We had the frank discussion about our plans and lack of progress that we should have been having all along. In the process, we brainstormed some exciting new ideas. In the days that followed we fleshed those out. The uninspired daily grind that working at Zanshin had become took on a new feeling of hopefulness. My co-worker Steve, who had also been in favor of the Amazon offer, gave a stirring speech about continuing on our own.

When it came time to give Amazon our final decision, we voted unanimously to turn them down. Knowing I’d previously been the strongest vote in favor of the Amazon offer, my co-worker Greg asked if I was sure. I replied, “I’m like the arrow that springs from the bow. No hesitation.”

It was a line spoken by Michael O’Hare as Jeffrey Sinclair in Babylon 5. I have used that sentiment a few times since then as a way to gauge my readiness for something — starting a family, for instance. If I can’t say that line with conviction I know I’m kidding myself.

Today came news that Michael O’Hare died. Nerds all over the web are paying him tribute for his role in a beloved space adventure, but his legacy is a little more personally meaningful to me. His memorable reading of that one line has attended every important decision of my life since he spoke it.

Who are the real monsters?

A British film about Americans in Mexico. That seemed odd. But it didn’t stop me from watching 2010’s Monsters on Netflix recently, and enjoying it.

It’s six years after a NASA probe to Jupiter’s moons crash lands on its return to Earth, “infecting” an area of Northern Mexico near the U.S. border with samples of alien life, which thrive there and multiply, growing huge and destructive. The U.S. has erected an enormous wall along its Mexican border and its military makes regular incursions across it to suppress the creatures and limit their spread. Our two main characters have to make it back to the U.S. while traveling dangerously near, and eventually through, the infected zone. Their journey has a vérité feel and is full of suspense, with a few moments of terror and some interesting character development. By the end I found it compelling enough to go online and see what opinions others had written about it.

I was disappointed by what I found. Without exception the reviews and opinions that I read evaluated Monsters as a conventional monster movie — that is, as a mere shocker — and by that metric many critics found it lacking in terms of horror and body count and creature biology and so on, though everyone commended the guerrilla filmmaking techniques and how far the tiny budget was stretched for the sake of producing credible special effects. The principal filmmaker, Gareth Edwards, is now being talked about as a hot new talent for directing sci-fi epics.

All of which was missing the point. Not one writer commented on the glaringly obvious subtext, the very reason the film was made and the answer to why a British filmmaker chose Mexico as his setting and Americans as his characters: it’s a story about the failure of America to adapt to a changing world.

[Spoilers follow.]

Continue reading “Who are the real monsters?”

Basket handle protocol

There is no hope, and here’s the proof: shoppers often stack empty store baskets with one handle positioned as shown.

It’s widely agreed that if we’re going to save the world, we have to plan beyond the next quarterly statement, stop being so selfish, reduce our footprint, eat less beef, burn less oil, invest in infrastructure, conserve resources for future generations. But how can we keep future generations in mind when we can’t even keep in mind the next shopper who has to stack an empty basket?

Please, let the future begin. Keep the next shopper in mind and move your empty basket handles to the sides.

Predicting the present

One day long ago, when the IBM PC was still new, my friend Mike asked me to imagine my ideal computer. I described something very like the IBM PC, but with more memory and a bigger hard drive — 50 megabytes, say, instead of 10 or 20. I couldn’t imagine any use for much more than that. (Today of course you can’t even buy a thumb drive that tiny.) I grudgingly allowed that a bitmap display might be more useful than the 80-column-by-24-line character terminal that PC’s had, but that was all I would consider adopting from the then-brand-new Apple Macintosh, which I dismissed as a silly toy unworthy of Real Programmers.

“Why?” I asked Mike. “What’s your ideal computer?”

Mike described something no bigger than an 8.5×11 sheet of paper and no more than an inch or so thick, whose entire surface was a full-color display. It could be carried in the hand or slipped into a backpack. “What about the CPU, where would that go?” I asked. I wasn’t getting it. Mike patiently explained that the whole system — CPU, RAM, video driver, power supply — was inside that little slab. I scoffed. Cramming everything into such a small space was obviously impossible, and no battery that could fit in such a thing would ever have enough power to spin a floppy disk drive for long. “Anyway, even if you could build it,” I told him, “it wouldn’t be as convenient as you’d like. You’d have to carry around a keyboard too and plug it in every time you wanted to use it.” No you wouldn’t, said Mike. The display could be touch-sensitive. The keyboard could be rendered on the screen as needed and input accepted that way.

This was 1984. What Mike described was pure science fiction. (In 1987 that became literally true, when the touch-controlled “padd” became a staple prop on Star Trek: The Next Generation.) Yet here I am, the proud new owner of a Nexus 7, the latest in high-powered touch-sensitive computing slabs that put even Mike’s audacious vision to shame.

It wasn’t the first time I’d had a failure of technological vision, nor was it the last.

Several years earlier, before even the IBM PC, I was spending a lot of afterschool hours at my friend Chuck’s house, and a lot of those hours on his dad’s home computer, one of the only ones then available: the beloved but now mostly forgotten Sol-20. (The TRS-80 and the Apple ][ were brand new and just about to steal the thunder from hobbyist models like the Sol-20.) It had a small black-and-white monitor that could display letters, numbers, typographical marks, and a few other special characters at a single intensity (i.e., it really was “black and white,” not greyscale). It looked like this:

The display was so adequate for my meager computing needs there in the late 1970’s that when the computer magazines I read started advertising things like Radio Shack’s new Color Computer (that’s what it was called — the “Color Computer”), I dismissed them as children’s toys.

Once, Chuck and I entertained the idea of making a little science fiction movie. A scene in Chuck’s script had a person’s face appearing on a computer monitor and speaking to the user. It was his plan to film this scene using his father’s computer. I said, “How are we going to make a face appear on a computer monitor?” I had only ever seen letters and numbers blockily rendered on it. Chuck pointed out that the monitor was really just a small TV. “Oh yeah,” I said, feeling stupid. It ought to be able to display anything a TV could. Of course we’d have to hook it up to a different source; obviously no computer could handle rendering full-motion video. Yet here I am, a software engineer at YouTube.

There’s more. In the mid 80’s, my sometime boss Gerald Zanetti, the commercial food photographer and computing technophile, once described his vision for composing and editing photographs on a high-resolution computer display. If a photograph included a bowl of fruit, he explained, he wanted to be able to adjust the position of an orange separately from the grapes and the bananas surrounding it. I said that such technology was far in the future. I’d seen graphics-editing programs by then, but they treated the image as a grid of undifferentiated pixels. Separating out a foreground piece of fruit from other items in the background simply was not feasible. Yet just a couple of years later Photoshop exactly realized Zanetti’s vision.

In the mid 90’s, when the web was new, my friend and mentor Nathaniel founded a new company, First Virtual, to handle credit card payments for Internet commerce. At the time there was no Internet commerce. Nathaniel and company invented some very clever mechanisms for keeping sensitive credit-card information entirely off the Internet while still enabling online payments. But I felt their system was too complicated to explain and to use, that people would prefer the familiarity and convenience of credit cards (turns out I was right about that), and that since no one would (or should!) ever trust the Internet with their credit card information, Internet commerce could never amount to much. Yet here I am, receiving a new shipment of something or other from Amazon.com every week or two.

Oh well. At least I’m in good company. I’m sensible enough finally to have learned that however gifted I may be as a technologist, I’m no visionary. Now when someone describes some fantastical new leap they imagine, I shut up and listen.

Mercy rhyme 2

Well this is turning out to be an odd specialty: writing clever poems to cheer up young women as they recover from serious injuries sustained in major disasters. (Previously.)

This time it was a cheerful colleague from YouTube named Sara. She received serious burns in a very narrow escape from a devastating apartment fire last week in San Francisco. Being YouTube, a lot of us recorded a get-well video for her. My message was the following poem.

To show that I care a
Lot about Sara
I’ve placed in my hair a
Silver tiara.

Does she rail and swear a-
Gainst chance so unfair, a
Cause for despair? Uh,
Never our Sara.

With her savoir faire, a
Smile she does wear. “Ah,
C’est la guerre” a-
Nnounces our Sara.

And here’s Sara at the hospital yesterday, reacting to her video greeting: