Friday, May 30, 2008

Smug Lisp Weenies and Lateral Thinking

I think I've hit upon one of the reasons for the perceived smugness (and weeniness?) of Lispers. They are often lateral thinkers.

I've spent the last year or so learning Lisp (using Scheme for a side project) and so I've pestered a lot of people on freenode's #lisp and #scheme (and a #emacs) and what usually happens is something like the following:

Vincent: So how do I do [[X]]? Lisper: Why do you want to do [[X]]? Vincent: Umm - for auto-didactic purposes? Lisper: You don't want to do [[X]] - you can but it doesn't make sense. You really should do [[Y]] instead. Here is how to do [[Y]]. Vincent: But damnit I want to do [[X]]. =Lengthy argument/discussion during which I realize that doing [[X]] is dumb.=

Hanging out on #lisp a lot, I see this kind of exchange all the time - so it is not just me. People on #lisp invariably want to know the entire context of a question, and when they find out, they generally suggest a solution which is lateral to the question posed.

There is probably an analogy with functions and macros here but I will let someone more erudite pursue it.

Now, lateral thinking is generally recognized as a quality of smart people, so it is hardly exclusive to Lispers. But Lispers are infamous for being an insular community, not friendly to people wanting to approach the language from one blub or another and so it's worth pursuing this topic a bit further.

I'd like to advance the following: the perceived unhelpfulness of Lispers is structural. It derives from the selection criteria operating on Lispers providing advice and "blubbers" looking for it. Here is why: Lispers are, generally, out of the box thinkers, or they wouldn't be using Lisp1. People asking for help on #lisp are 1) new to Lisp and 2) almost surely trying to get a particular thing done, right now. If they were voracious auto-didacts without a particular goal in mind, besides learning, they would likely be content to just figure out any questions themselves. Finally, Lisp is different, which means people coming from other programming languages will probably be laden with a lot of habits which don't serve well in Lisp. As a consequence, they will often be asking questions that amount to "how do I make Lisp act like PHP/Python/Whatever". These questions are exactly the kind of questions that a seasoned, lateral thinking Lisper, is likely to want to divert into other, more lispy questions. And they probably should - it doesn't make a lot of sense to answer the wrong question with the right answer.2

Nevertheless, the overall effect is a kind of impedence mismatch between learners of Lisp and the Lisp learned. It wouldn't surprise me to find out that this observation, more or less, has been made before. But maybe re-iterating it can somehow help make that impedance mismatch a bit less of a barrier to entry for people interested in the language.


1: It is hard to argue that purely on the basis of ease of use (libraries, set up time, familiarity) that Lisp is a win over "batteries included" languages like Python.

2: There is something else interesting here, but it is somewhat lateral to the overall point of this post. Lisp, a language which will let you do anything, no matter how poorly advised, seems to be, in some larger sense, conceptually restrictive. If it wasn't, the question "how can I do [[X]]" would always make sense. What this may reflect is that the community exerts pressure to regularize the use of Lisp which other languages regulate with syntax and/or limitations on semantics.

Monday, May 12, 2008

On Inform 7, Natural Language Programming and the Principle of Least Surprise

I've been pecking away at Inform 7 lately on account of its recently acquired Gnome front end. For those not in the know, Inform (and Inform 7) is a text adventure authoring language. I've always been interested in game programming but never had the time (or more likely the persistence of mind) to develop one of any sophistication myself. Usually in these cases one lowers the bar, and as far as interactive media goes, you can't get much lower, complexity wise, than text adventures.

Writing a game in Inform amounts to describing the world and it's rules in terms of a programming language provided by Inform. The system then collects the rules and descriptions and creates a game out of them. Time was, programming in Inform used to look like:

Constant Story "Hello World";
Constant Headline "^An Interactive Example^";
Include "Parser";
Include "VerbLib";
[ Initialise;
  location = Living_Room;
  "Hello World"; ];
Object Kitchen "Kitchen";
Object Front_Door "Front Door";
Object Living_Room "Living Room"
  with
      description "A comfortably furnished living room.",
      n_to Kitchen,
      s_to Front_Door,
  has light;

Which is recognizably a programming language, if a bit strange and domain specific. These days, writing Inform looks like this: (from my little project):

"Frustrate" by "Vincent Toups"
Ticks is a number which varies.
Ticks is zero.
When play begins:  
Now ticks is 1.

The Observation Room is a room. "The observation room cold and
surreal. Stars dot the floor underneath thick, leaded glass, cutting
across it with a barely perceptible tilt. This room seems to have been
adapted for storage, and is filled with all sorts of sub-stellar
detritus, sharp in the chill and out of place against the slowly
rotating sky. Even in the cold, the place smells of dust, old wood
finish, and mildew. [If ticks is less than two] As the sky cuts its
way across the milky way, the whole room seems to tilt.  You feel
dizzy.[else if ticks is less than four]The plane of the galaxy is
sinking out of range and the portal is filling with the void of
space. It feels like drowning.[else if ticks is greater than 7]The
galactic plane is filling the floor with a powdering of
stars.[else]The observation floor looks out across the void of space.
You avert your eyes from the floor.[end if]"

Every turn: Now ticks is ticks plus one.
Every turn: if ticks is 10:
decrease ticks by 10.

As you can see, the new Inform adopts a "natural language" approach to programming. As the Inform 7 website puts it

[The] Source language [is] modelled closely on a subset of English, and usually readable as such.

Also reproduced in the Inform 7 manual is the following quote from luminary Donald Knuth:

Programming is best regarded as the process of creating works of literature, which are meant to be read... so we ought to address them to people, not to machines. (Donald Knuth, "Literate Programming", 1981)

Which better than anything else illustrates the desired goal of the new system: Humans are not machines! Machines should accommodate our modes of expression rather than forcing us to accommodate theirs! If it wasn't for the unnaturalness of programming languages, the logic goes, many more people would program. The creation of interactive fiction means to be inclusive, so why not teach the machine to understand natural language?

This is a laudable goal. I really think the future is going to have a lot more programmers in it, and a primary task of language architects is to design programming languages which "regular" people find intuitive and useful. For successes in that arena see Python, or Smalltalk or even Basic. Perhaps these languages are not the pinnacle of intuitive programming environments but whatever that ultimate language is, I doubt seriously it will look much like Inform 7.

This is unfortunate, because reading Inform 7 is very pleasant, and the language is even charming from time to time. Unfortunately, it's very difficult to program in1, and I say that as something of a programming language aficionado. It's true that creating the basic skeleton of a text adventure is very easy, but even slightly non-trivial extensions to the language are difficult to intuitively get right. For instance, the game I am working on takes place on a gigantic, hollowed out natural satellite, spinning to provide artificial gravity. The game begins in a sort of observation bubble, where the floor is transparent and the stars are visible outside. Sometimes this observation window should be pointing into the plane of the Milky Way, but other times it should be pointing towards the void of space because the station's axis of rotation is parallel to the plane of the galaxy. The description of the room should reflect these different possibilities.

Inform 7 operates on a turn based basis, so it seems like it should be simple enough to create this sort of time dependent behavior by keeping track of time but it was frustrating to figure out how to "tell" the Inform compiler what I wanted.

First I tried joint conditionals:

  When the player is in the Observation Room and
the turn is even, say: "The stars fill the floor."

But this resulted in an error message. Maybe the system doesn't know about "evenness" so I tried:

  When the player is in the Observation Room and
the turn is greater than 3, say "The stars fill the floor."

(Figuring I could add more complex logic later).

Eventually I figured out the right syntax, which involved creating a variable and having a rule set its value each turn and a separate rule reset the value with the periodicity of the rotation of the ship, but the process was very frustrating. In Python the whole game might look, with the proper abstractions, like:


while not game.over():
    game.describe_location(player.position);
    if (player.position == 'The Observation Room' and
         game.turn() % 10):
        print "The stars fill the floor."

Which is not perhaps as "englishy" as the final working Inform code (posted near the beginning of this article) but is much more concise and obvious.

But that isn't the reason the Python version is less frustrating to write. The reason is the Principle of Least Surprise, which states, roughly, that once you know the system, the least surprising way of doing things will work. The problem with Inform 7 is that "the system" appears to the observer to be "written english (perhaps more carefully constructed that usual)". This produces in the coder a whole slew of aassumptions about what sorts of statements will do what kind of things and as a consequence, you try a lot of things which, according to your mental model, inexplicably don't work.

It took me an hour to figure out how to make what amounts to a special kind of clock and I had the benefit of knowing that underneath all that "natural English" was a (more or less) regular old (prolog flavored) programming environment. I can't imagine the frustration a non-programmer would feel when they first decided to do something not directly supported or explained in the standard library or documentation.

That isn't the only problem, either. Natural english is a domain specific language for communicating between intelligent things. It assumes that the recepient of the stream of tokens can easily resolve ambiguities, invert accidental negatives (pay attention, people do this all the time in speech) and tell the difference between important information and information it's acceptable to leave ambiguous. Not only are computers presently incapable of this level of deduction/induction, but generally speaking we don't want that behavior anyway: we are programming to get a computer to perform a very narrowly defined set of behaviors. The implication that Inform 7 will "understand you" in this context is doubly frustrating. And you don't want it to "understand," you want it to do exactly.

A lot of this could be ameliorated by a good piece of reference documentation, spelling out in exact detail the programmatic environment's behavior. Unfortunately, the bundled documentation is a big tutorial which does a poor job of delineated between constructs in the language and elements of it. It all seems somewhat magical in the tutorial, in other words, and the intrepid reader, wishing to generalize on the rules of the system, is often confounded.

Nevertheless, I will probably keep using it. The environment is clean and pleasant, and the language, when you begin to feel out the classical language under the hood, is ok. And you can't beat the built in features for text based games. I doubt that Inform 7, though, will seriously take off. Too many undeliverable promises.

1 This may make it the only "Read Only" programming language I can think of.