Mike Schaeffer's Weblog
Fri, 04 Mar 2005
General posts on a topic don't go at the root...
Maybe this should have been obvious from the beginning, but I'm no longer putting "general interest" blog posts at the root for the topic. Rather, those posts are now going under a "general" subtopic of the root.

The problem with making general interest posts at the root of a topic is that there's then no way to watch only the general topics. If you look at the root topic, you get the whole topic.

reddit this! Digg Me!

[/tech/this_blog] permanent link

A few good Lisp and Scheme (and Smalltalk) Related Links
It never ceases to amaze me how much good material there is online. Here's some more:

  • Olin Shiver's History of the T implemenatation of the Scheme programming language.
  • Aubrey Jaffer has some interesting material on interpreter performance issues at his SCM site.
  • Alan Kay's Early History of Smalltalk
  • In 1994, Richard Stallman started a debate (flamewar?) on comp.lang.tcl with a post entitled Why you should not use Tcl. The Guile scripting language was the logical outgrowth of this.
  • Kent Pitman has posted a bunch of his writings relating to Lisp and SCheme. Among other things, he edited the Common Lisp Hyperspec, which is an on-line version of the Common Lisp specification.
  • Peter Siebel has written a book, Practical Common Lisp, and has gotten permission to put it online indefinately.

    Ps: Be sure to check out Olin Shiver's philosophy of undergraduate advising. It's an example to be followed. ;-)

    reddit this! Digg Me!
  • [/tech/lisp] permanent link

    Outsourcing vs. Offshoring
    I'm writing some content for a future post on the offshoring of jobs overseas, but I want to clear something up before it gets posted: Outsourcing and offshoring are two different and orthogonal concepts. This seems to be something that gets misunderstood a great deal, but simply put, outsourcing is the movement of jobs to a different company and offshoring is the movement of jobs to a different country. Either one can be done without the other.

    The scenarios that people tend to get upset about (at least in the United States) are the scenarios involving offshoring, the movement of work overseas. Outsourcing, however, does not necessarily imply that the work gets moved to a different country: it's very common for work to be outsourced to another American business employing American workers. An example of this is hiring a Madison Avenue firm to put together an ad campaign. Sure, it'd be possible to develop the talent in house to do this yourself, but there are many advantages in outsourcing the work to a more specialized vendor.

    reddit this! Digg Me!

    [/tech/business] permanent link

    Color Picker...
    This is cool. What it is is a web-based color picker that automatically gives you a couple different kinds of complementary colors.

    reddit this! Digg Me!

    [/tech/general] permanent link

    Sony Ericsson T-637
    A few months ago, my wife and I recently switched from a Sanyo 4700 and a 4900 on Sprint PCS to a pair of Sony Ericsson T-637's on bCingular Wireless. Overall, the switch has been an improvement, but there are still a few nagging issues:

  • Cingular's selection of Java games is much sparser and more expensive than Sprint's.
  • There's no "Phone Ringing" Ringtone on the phone, just a bunch of generic and/or unrecognizable music files.
  • There are buttons on the side of the phone that activate the web browser and camera. These are pretty easy to hit by accident.
  • Sanyos and Nokias have this problem too, but the Sony doesn't really handle the case of multiple directory entries with the same phone number. When called by someone at a number that for which I have multiple entries, I'd really like to see a list of all of the entries containing that number. (This would help handle the case of two people each with cell phones and with one home number.)
  • The incoming call logs are by number, not by call. This makes it difficult to tell when you've missed multiple calls from the same number.
  • The incoming call logs rely on automatic horizontal scrolling to reveal information like time of call and number of calls missed. This means that you have to select a log entry and sit on it for a few seconds while the phone scrolls the information you want into view. I'd much rather have some kind of details/summary view toggle button on the side of the phone. Of the four side mounted buttons, surely one could be for this.
  • There's a music editor built in that lets you compose custom ring tones. However, it only lets you work with a fixed set of clips, so it loses its appeal very quickly.

    I guess that looks like a lot of complaining, but otherwise the phone is very nice. The last phone I've liked as much is my old Nokia 8260 (and the 6160 before that). The Sanyo 4900 doesn't even come close. I'm happy enough with this phone to consider buying another Sony Ericsson. (The new W800i looks pretty nice...)

    reddit this! Digg Me!
  • [/tech/products] permanent link

    Wed, 02 Mar 2005
    I guess I had forgotten how slow I/O was, particularly bad I/O.
    I'm in the middle of developing a Scheme compiler for a future release of vCalc. While I've been developing the code, I've peppered it full of debugging print statements that look something like this:

    (format #t "compiling ~l, tail?=~l, value?=~l" form tail? value?)

    with the output statements in place, the compiler takes about 250-300ms to compile relatively small functions. Not great, particularly considering that there's no optimization being done at all. Anyway, on a hunch I removed the format statements, and execution time improved by a couple orders of magnitude to a millisecond or two per function. That's a lot closer to what I was hoping for at this stage of development.

    On the other hand, I hadn't realized that my (ad hoc, slapped together in an hour) format function was running quite that slowly. I think it'll end up being an interesting optimnization problem sooner or later.

    reddit this! Digg Me!

    [/tech/lisp] permanent link

    Tue, 01 Mar 2005
    Message Dialog
    This be should part of the Win32 API if it's not already. Basically, it amounts to a variant of the MessageBox API that allows custom button labels, rather than just "Yes", "No", "Abort", "Retry", etc.

    Maybe this kind of API would have made abominations like this less likely:



    At least users might be able to avoid calling errors "OK", of all things...

    reddit this! Digg Me!

    [/tech/general] permanent link

    Programming Well: Embrace Idempotence, Part 2 (It works at runtime too)
    Idempotence has benefits at a program's run-time, as well as at build time. To illustrate, consider the case of a reference counted string. For the sake of example, it might be declared like this (In case you're wondering, no, I don't think this is a production-ready counted string library...):

    struct CountedString
    {
      int _references;
      char *_data;
    };

    CountedString *makeString(char *data)
    {
      CountedString cs = (CountedString *)malloc(sizeof(CountedString));

      cs->_references = 1;
      cs->_data = strdup(data);

      return 1;
    }

    CountedString *referToString(CountedString *cs)
    {
      cs->_references++;
      return cs;
    }

    void doneWithString(CountedString *cs)
    {
      cs->_references--;

      if (cs->_references == 0)
      {
        free(cs->_data);
        free(cs);
      }
    }

    // ... useful library functions go here...


    The reference counting mechanism buys you two things. It gives you the ability to delete strings when they're no longer accessible; It also gives you the abilty to avoid string copies by deferring them to the last possible moment. This second benefit, known as copy-on-write, is where idempotence can play a role. What copy on write entails is ensuring that whenever you write to a resource, you ensure that you have a copy unique to to yourself. If the copy you have isn't unique, copy-on-write requires that you duplicate the resource and modify the copy instead of the original. If you never modify the string, you never make the copy.

    This means that the beginning of every string function that alters a string has to look something like this:

    CountedString *alterString(CountedString *cs)
    {
      if (cs->_references > 1)
      {
        CountedString *uniqueString = makeString(cs->_data);
        doneWithString(cs);
        cs = uniqueString;
      }

       \\ ... now, cs can be modified at will

       return cs;
    }

    Apply a little refactoring, and you get this...

    CountedString *ensureUniqueInstance(CountedString *cs)
    {
      if (cs->_references > 1)
      {
        CountedString *uniqueString = makeString(cs->_data);
        doneWithString(cs);
        cs = uniqueString;
      }

      return cs;
    }

    CountedString *alterString(CountedString *cs)
    {
      cs = ensureUniqueReference(cs);

      \\ ... now, cs can be modified at will

      return cs;
    }


    Of course, ensureUniqueInstance ends up being idempotent: it gets you into a known state from an unknown state, and it doesn't (semantically) matter if you call it too often. That's the key insight into why idempotence can be useful. Because idempotent processes don't rely on foreknowledge of your system's state to work reliably, they can be a predictable means to get into a known state. Also, If you hide idempotent processes behind the appropriate abstractions, they allow you to write code that's more self documenting. A function that begins with a line like cs = ensureUniqueInstance(cs); more clearly says to the reader that it needs a unique instance of cs than lines of code that check the reference count of cs and potentially duplicate it.

    Next up are a few more examples of idempotence, as well as a look into some of the pitfalls.

    reddit this! Digg Me!

    [/tech/programming/idempotence] permanent link

    Michael Kaplan's Blog and a Few Other Good Links
    Another useful blog from Microsoft. Michael Kaplan has been blogging for quite some time on internationalization and other Unicode-related issues. His blog full of deep, technical information on a part of Windows that seems to get overlooked a lot. I've been starting the very first steps of getting vCalc (and my Scheme interpreter) to be Unicode aware, so his blog has been timely reading.

    I've also found, via Lambda the Ultimate, a website dedicated to Alexander Stepanov's papers and code. Stepanov is one of the principals behind the C++ STL (STepanov and Lee) Standard Template Library.

    reddit this! Digg Me!

    [/tech/general] permanent link

    New York Laundromat
    Over the last several months, I've been spending a great deal of time in New York City on business. In that time, I have never been quite as suprised by prices as I have tonight. I wasn't even trying to do anything all that unusual, just two loads of laundry.

    Normally, I'd expect that two loads of laundry would cost about $6. The washer would be $1.50 or so per run, and the dryer would be another $1.50 per run, for a total of $6. Maybe even $7.50, if you decide to run a second dryer cycle. Even in New York (west Midtown Manhattan), I've been in apartments recently that charge about that much.

    However, this apartment is special: they use a "smart" card system to manage payments. There's a dispenser on the side of the wall that sells $7 cards for $10 (cards themselves cost $3). The dispenser also allows you to reload cards in $5 and $10 increments. Once you have a card, there are slots in each of the washers and dryers that accept the card and debit from it the $2.50 it takes to buy a cycle in one of the machines. Yes, you read that right: $2.50. $2.50 in my apartment complex buys a 34 minute washer cycle or a 30 (yes, 30) minute dryer cycle.

    So tonight, I spent $15 (200% of my estimate) and got this:

  • A $3 "smart" Card to carry around and not lose
  • Two complete loads of laundry that will inevitably end up damp, thanks to the pathetic dryer cycle.
  • $2 of "change" on my "smart" card that I will never get to spend. (Since every machine in the laundromat costs $2.50, and the card can only be reloaded with $5 or $10)

    The part of this that bothers me the most is the $3 surcharge on the smart card. Thanks to the pricing structure of the laundromat, the $3 surcharge really amounts to a $5 surcharge. This means that someone was either stupid enough not to notice that customers would always end up with $2 of useless change, or was malicious enough to use this as a sleazy way to bilk customers out of an extra $2. Not to mention that I get the hassle of trying not to lose this stupid card, lest I want to drop another $5 on yet another card.

    reddit this! Digg Me!
  • [/personal/nyc] permanent link