28 July 2006

Human visual navigation

I think the region of the screen I can concentrate on at once is quite small, maybe twelve words wide and six lines tall. But then why do I prefer two large high-resolution screens to one low-res screen? I can't really use all that screen space, can I?

Let's talk about the navigation features provided by human vision. Although I have this 12x6 mental "window", the window doesn't stay still. I can read a whole screenful of text without touching the mouse. Human vision has built-in scrolling. I can take in more of the screen at once by sacrificing attention to detail; or I can concentrate on one line of code, at the cost of ignoring everything else for a moment: visual zoom. If I look away, then when I look back, my eyes easily snap to where I was. This is kind of like Alt+Tab in that it lets me hop back and forth between different things; call it visual switching. If I need to look for something, I'll zoom out, skim down without reading, find it, and zoom back in, all without thinking: visual search.

With a huge screen, I can scroll, zoom, switch, and search without touching the keyboard or mouse. With a smaller screen, I have to use the mouse or keyboard to navigate. Each motion takes time and a little bit of brainpower; and each time the screen changes, it takes me a moment to find my place. Eyeball scrolling is superior to software scrolling. Eyeball switching is superior to Alt+Tab.

Having dispensed with that paradox, I want to talk about the 12x6 window and what it means for PL and IDE design. More to come.

25 July 2006

To do

More possible side projects:

  • Blog about irrationality and game theory. I promised D.E. something about this many months ago.
  • Implement long integers for Try Scheme. (Java's implementation is about 4400 lines; Python's is about 3200 lines, including comments and boilerplate junk. Neither one uses two's complement to represent negative numbers, which surprises me. Maybe division is a lot harder to implement in two's complement?)
  • Get Try Scheme working in Safari (the most obvious problem is that Safari doesn't have Object.isPrototypeOf).
  • Implement a built-in manual and tutorial for Try Scheme.
  • Write a story.

18 July 2006

Hiding algorithms and data structures

In Java, you might write:
class Thing {
    ...
    public int getCurrentSize() {
        int size = getBaseSize();
        for (SizeEffect se : getWorld().getAllEffectsEnchanting(this)) {
            size += se.getMagnitude();
        }
    }
}

In Python 2.4 or later, you might write this instead:

class Thing:
    ...
    def getCurrentSize(self):
        return self.baseSize + sum(
          se.magnitude for se in self.world.getAllEffectsEnchanting(self))

If that's not entirely clear yet, just read on. I'll come back to it.

In Inform 7, you would write this:

To decide which number is the current size of (subject - a thing):

Decide on the base size of the subject plus the total magnitude of the size effects enchanting the subject.

I hope that clarifies what the Python version is trying to say. The Python expression sum(se.magnitude for se in ...) is just a way of saying “the total magnitude of ...”.

Ah, but in Inform, you don't use anything that resembles loop syntax to iterate through the size effects. And you don't explicitly query anybody to get the set of relevant objects. You just state your requirements. You don't build data structures explicitly, either—I wouldn't want to post an example World object here, but I can show you the complete Inform code:

A thing has a number called the base size. The base size of a thing is usually 1. The base size of a person is usually 5.

A size effect is a kind of thing. A size effect has a number called the magnitude.

Enchantment relates various size effects to various things. The verb to enchant (he enchants, they enchant, he enchanted, it is enchanted, it is enchanting) implies the enchantment relation.

That's all. The last sentence is just a convenience so that later in your program, you can write “The giant growth spell is a size effect with magnitude 3. It enchants the wombat.” or “Now the wicked ginormosity spell enchants everything.” or “Every turn, if anything is enchanting the player, say ‘You feel prickles all over your skin.’”

Of course, Inform is probably cheating a little bit: in its niche problem domain, there are only ever a few hundred objects in an entire program. So it can implement the implied searches naively. Still, with a little whole-program analysis, the technique could scale.

Why does this feel so new? We've been there with Prolog and SQL, right? I guess Prolog had unrelated problems, and SQL is still awfully cumbersome to get to. I'm awfully impatient about these features showing up in a language I can use every day.

07 July 2006

Duck-typing and Scheme

Duck-typing advocates occasionally say that querying the type of an object is unnecessary. Certain Pythonistas are fond of this idea. I just don't see it.

Maybe querying the concrete type is unnecessary. (Aside: Python has a builtin, isinstance(), that does just that—but I found out a week or two ago that an object can lie to isinstance() about its type. It's just the most absurd design ever.) But once in a while, I need to know whether a given object can swim, at runtime, preferably without having to put it in the water. Surely in a well-designed language, these questions can be answered without unduly revealing how an object is implemented.

For example, in Scheme, you can't ask if a number is a floating point number, as opposed to a native int (fixnum in Scheme jargon), big-integer, rational, or big-decimal. But you can ask if the number is exact, meaning basically that it hasn't been subjected to rounding. You can ask if a number is an integer or not: (integer? x); but you are actually asking about the number, not its type. So (integer? 1.79e123) is true, as is (real? 1).

For numbers, the difference between querying an object's characteristics and querying its concrete type might seem unimportant. Also, numbers are a special case where the concrete type matters a whole lot, for performance. (The next Scheme standard will add a bunch of procedures like (fx+) that only work on fixnums.) But when you start talking about objects, the difference is whether or not you support duck typing, which I think is a big deal. Languages should make it easy to query an object's interface and inconvenient to query its implementation.