Newsgroups: rec.arts.int-fiction
Path: news.duke.edu!newsgate.duke.edu!nntp-out.monmouth.com!newspeer.monmouth.com!news.maxwell.syr.edu!news-out.visi.com!hermes.visi.com!uunet!ash.uu.net!world!not-for-mail
From: buzzard@TheWorld.com (Sean T Barrett)
Subject: Re: Using multiple dispatch to write text adventures
Sender: news@world.std.com (Mr Usenet Himself)
Message-ID: <Grwz9p.4Fo@world.std.com>
Date: Fri, 22 Feb 2002 03:05:49 GMT
References: <871yfgmxec.fsf@alice.dynodns.net> <e9ceddbb.0202200337.19acc91@posting.google.com> <a50f0f$15j$1@reader1.panix.com> <87vgcrls2n.fsf@alice.dynodns.net>
Nntp-Posting-Host: shell01.theworld.com
Organization: The World Public Access UNIX, Brookline, MA
X-Newsreader: trn 4.0-test72 (19 April 1999)
Lines: 192
Xref: news.duke.edu rec.arts.int-fiction:100498

John Wiegley  <johnw@gnu.org> wrote:
>So, forget that I'm using Lisp.  The end product may have nothing to
>do with Lisp.

By the by, you generally shouldn't post huge source samples like
that. A snippet that fits on a single screen (24 lines) is probably
a reasonable rule-of-thumb limit.

Now, gentle readers, first I'm going to offer some language-design
language-thinking criticism (which, hey, I may be wrong about, we're
talking about something fairly wacky here); and then after that pedantry
I'll offer my opinion about the relevance of this idea to IF.

>It's the idea of multiple dispatch that I'm testing.
>It sounds like what I need now is a genuine proof of a real problem,
>like re-implementing Alice, to show whether the system actually offers
>any real power over current methods.

It's an interesting idea that I considered and rejected when I
was designing my MUD development system. That system used a C-like
syntax for message dispatch (compare Perl) where
    message(obj, p1, p2, p3)
was a message to 'obj'. This is STILL object-oriented code; and
one could argue that a language where
    message(p0, obj, p2, p3)
got dispatched to 'obj' was also object-oriented.

>One thing that multiple dispatch does allow you to do is to enrich
>base types without modifying them.
[snip]
>But what if you want to specialize "cut" on the base object, relative
>to swords?  It would have to be done like this:

There's really no reason why
    message(obj1, obj2, p2, p3)
(where that's a multi-dispatch) couldn't be considered object-oriented;
for example, the method might live on either obj1 or obj2 but use some
kind of type overloading to resolve.

No matter how you implement multiple dispatch, you really do have to
view it as "modifying" the base type in some sense.

>Yet this pretty much erases the abstractions gained from OO, by
>creating a system in which every object may or may not need to know
>about the type of every other object.

This is the nature of the *problem domain*, not the nature of OO.
IF already veers wildly from traditional OO by defining lots of
unique objects with custom code. (You can argue they're singletons,
but if you compare what's going on in practice with what singletons
are traditionall for, you'll see the difference--the IF objects
are all of a common 'simulation type', just with different behaviors.)

So either you consider IF-OO to be "real OO" or not; I don't think
multi-dispatch really changes that.

>  defmethod sharpen sword object
>    Sharpening the sword, using object.
>
>  defmethod cut object sword
>    Cutting an object, using the sword.
>
>Now, no _object_ knows about any other.  It is the associations that
>know everything about their possible conjunctions.

To put what I was saying above more concretely: we tend to think of
methods and living on objects (or their classes), but this is an
implementation detail; if the above is an example of code that's
not "on" any particular class/object, then

   defmethod take object
     Picking up an object

wouldn't need to be on any particular class/object either. We
just traditionally consider it that way, since OO isn't traditionally
multi-dispatch.

Ok, enough pedantry.

Now, as to IF:

I don't think this is interesting because of the following issues:
 1. N-way interactions are rare due to simulationism
 2. rules for selecting best method are human-incomprehensible
 3. N-way dispatch can be faked with simple obvious code that
       is no less well-structured
 4. N-way dispatch syntactic sugar removes the ability to apply some
       programmatic resolution methods

I'm impatient with raif right now so I'm going to write these only briefly.

1. Simulationism

On the simulationist mud I worked on, we had a combat system.
HIT NPC WITH SWORD, right? The following objects wanted to contribute
to the outcome of the attack:
   the attacker's skill-system object (attack skill)
   the attacker's body object (strength, etc.)
   the attacker's weapon (the SWORD)
   the defender's shield[s] (including magic shields)
   the defender's skill-system object (defending skill)
   the defender's body object (e.g. dexterity, encumberance state)

The solution to this is not to define a 6-way multiway dispatch,
where ONE rule wins and determines the outcome, since how can that
reasonably cope with both a magic sword and a magic shield and
the player being really skillful? The solution is to write a
single "combat formula" which is some code with lots of hooks that
call into the other objects in a traditional single-dispatch fashion
and allow them to override it in various ways.

You can see the same things going on in IF for "CUT OBJECT WITH SWORD",
involving sophisticated multi-stage resolution systems where different
objects (including objects not even mentioned in the command, e.g. with
Inform's react_before) are allowed to participate. Platypus and Tads3
are the front-runners in sophistication here, I believe.

2. Incomprehensible rules

What happens if I

  defmethod cut object sword
    (blah blah blah)
  defmethod cut gem object
    (blah blah blah)

How do we decide which of these runs? If the defmethod formal
arguments can be arbitrary types from an OO tree (e.g. weapon,
etc.), then the way to resolve it is rather unclear. Existing
systems use a formal staged multi-step priority scheme IN CODE,
see above, so it's fully configurable with all the power of the
language.

If you don't use code, I think you'll end up with something like
C++ function overloading rules, which involve a bizarre multiway
match that few humans can correctly predict.

3. Can fake it equally structured

The "floating associations" you describe above, not part of
any object, are just as poorly structured; since they're not
associated with either object, how do I (as a coder/maintainer)
know about them? Where do I go to find them?

Current practice puts these on one object or the other, with an
if to test for the other object. That seems to me to be GOOD;
if there's a seeming custom interaction between X and Y, at least
I know it'll be found somewhere in either X's code or Y's code;
with multi-dispatch associations, I'd have a third place to look,
the pool of floating multi-dispatch associations.

4. programmatic solutions useful

In addition to the action-verification schemes I mentioned before,
Inform happens to be uniquely powerful at addressing these things,
IN A HUGELY KLUDGED FASHION admittedly, but I think any multiway
dispatch will be kludged.

Inform deals with action verification using an "implicit swich
on action" in "before" and "after" routines. In languages like
Tads, each of these before-verb actions becomes it's own routine.
I'm sure Tads has some mechanism to do something similar, but this
means in Inform you can do stuff like:

   before [;
      Insert, PutOn:
         if (second == hollow_banana)
            "Look, the same multi-way dispatch for TWO methods,
            incredibly concise.";
   ],

which can get even more complicated with things like

   react_before [;
      ... a bunch of common code that's run for ALL verbs ...
      Insert, PutOn:
         ... common code for all of this verb ...
         if (noun == banana && second == altar) {
            ... some special case code ...
            if (action == #Insert) {
               ... some special case for only one verb ...
            }
            ... more special case for both verbs again ...
         }
    ],

Etc. etc. etc.

Finally, like DanS said, I just don't think it comes up often
enough to be worth it.

SeanB
