# Frobs and other useless junk

Andrew Bakun (abakun@scinc.com)
Mon, 5 Aug 1996 13:37:14 PDT

- Messages sorted by:[ date ][ thread ][ subject ][ author ]

    At 11:40 AM 8/5/96 PDT, Michael Brundage <anomaly@u.washington.edu> wrote:
    >How can you do frobs in-db already?  Simple: Let's say you create an
    >abstract object called $value defining a generic MOO-value interface
    >(with verbs like add(), multiply(), and so on).  Subclass it into
    >separate objects (one for each type you wish to implement), even
    >subclassing these if you want.

    We've done this on E_MOO, with the full intent of converting them to true
    frobs once server support exists for it.  We called them datatypes though.
    And we've taken the indirect route, $type.hash_table, $type.stream,
    $type.table, etc.

    I'm hesitant to discuss the actual design and implementation though, it's
    long, and could start religious wars. :)

    >MOO is not all things object-oriented.  It seems to
    >me that adding in-db support for frobs is just going to triple the
    >overhead (especially if done in this way) for almost no gain, since they
    >can already be done in-db.  Moreover, it'll totally obfuscate MOO-code;
    >when I see thing:(vrb)(@args)  I expect 'thing' to be an honest-to-God
    >object, not just any possible MOO  value.

    (that looks like a typo... should it have been "It seems to me that adding
    in-server support for frobs..."?)
    MOO may not be all things OO, but I believe this is mostly because of the
    lack of other true OO concepts that the server should support, such as
    non-overridable methods.  The lack of non-overridable methods has made all
    accesses for things go through third parties instead of directly in the most
    widely used core database.

        $object_utils:has_verb(object, verbname);
    instead of
        object:has_verb(verbname);

    The problem with this is that in an OO language, ALL of the basic types
    should have object equlivents, that way, when you do call thing:verb(@args),
    if thing is not an object, it gets promoted to one, and then the call is made.

    >try
    >  my_vector1 = $value_factory:create("vector", {1, 2, 3, 4});
    >  my_vector2 = $value_factory:create("vector", {5, 6, -1, 0});
    >catch (e)
    >  player:tell("Error creating vector: "+$value.string:print(e));
    >endtry

    It's going through a third party to create them.  Not that this is all bad,
    since you have to call a method on the object to get an instance of it.
    Assuming we had a vector type on E_MOO, we'd use $type.vector:new() to get a
    vector instance.

    Your code example is a little confusing also.  I can't figure out why you'd
    have $value.string define a :print method that would handle any type.  I
    think it would make more sense to define a frob/datatype to handle values of
    the same type that e is, and do:

        player:tell("Error creating vector: " + e:tostr()

    (which we thought would be wise and that we've done on E_MOO).  This is
    where frob support comes in handy.  You can stop creating utility methods
    that think they know how to handle every possible type, and pass the actual
    operation off to the value itself and tell it to do something.  (you could
    have named it :print above, it doesn't matter, I perfer :tostr, since then
    you know what type it's going to return).  Of course, if not using an
    instance, you could still define a $type:tostr, and then call
    $type:tostr(e), which would then dispatch to e:tostr(), if you like the
    procedural approach.

    >return $value.vector:convert_to_list(my_vector1:add(my_vector2));

    Mmh.. what does $value_factory:create return?  An object?  It would have to
    in order for the above line to work.

    >This scheme is at least as workable as "frobs," with a comparable amount
    >of overhead and the bonus that you can do it *now*, without any server
    >hacks.

    Comparable amount of overhead?  Assuming your example above actually would
    work with no server mods, there would actually be a large amount of overhead
    in the constant object creation, destruction, and garbage collection that
    needs to go on.  If frobs were in server, then garbage collection is no more
    overhead than for other MOO values.

    >It's also totally clear what is going on, just by looking at the
    >code.  If you don't like the extra level of indirection, you can always
    >create synonyms on #0, such as $array == $value.array   Notice that you
    >can also create new types to your heart's content, and create types to
    >encapsulate all existing MOO types (and operations on them).

    The degree of clearness completely depends on the code being used, not the
    semantics of the language and it's type support.

      (a)  object = $string_utils:explode("bone->head", "->");

      (b)  stream = $type.stream:new(...);
           lines = stream:read(10);

      (c)  stream = $type.stream:new(...);
           lines = $type.stream:read(stream, 10);

    (a) is totally misleading, no matter what kind of typing the language
    enforces.  (b) is what true frob support would look like, as you can see, we
    are asking the stream we just created to return the next 10 lines.  (c) is
    how it currently looks on E_MOO, not that bad, but (b) is still better, I
    think, from a code maintaining and abstraction standpoint.

    Built in support for custom types, frobs, makes code easier to read and
    maintain, and abstracts complicated backends even more (you should see the
    stream datatype object, it's complicated, and it's only half done).  Yes,
    things still need to go through 'third parties' (in as much as handler
    objects for the datatypes are considered 'third parties'), but they are
    behind the scenes, away from the programmer.

    >Of course, you can't do my_vector1+my_vector2, but (1) MOO is not C++
    >(thank God), and (2) you'd have a similar problem with frobs, since
    >$call_verb(my_vector1, "+", my_vector2) is still going to have to check
    >the types of my_vector1 and my_vector2.

    Well, this depends on implementation, and anything that is actually doing an
    operation needs to have types checked anyway.  All of the methods on E_MOO
    that handle datatypes are required, per our design, to check the type of the
    datatype they were passed before doing any kind of manlipulations with/on
    it, raising an error if it's an incompatible type.  I personally do not want
    operator overloading in MOO, the entire thing would get overly confusing.

        vector_sum = $type.vector:add(vector1, vector2)
        vector_sum = vector1:add(vector2)

    Either is fine with me, both read fine.

    Its debatable if C++ is a good example of OO.

    Andy.