[% setvar title True Polymorphic Objects %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

True Polymorphic Objects

VERSION

  Maintainer: Nathan Wiger <nate@wiger.org>
  Date: 25 Aug 2000
  Last-Modified: 16 Sep 2000
  Mailing List: perl6-language-objects@perl.org
  Number: 159
  Version: 2
  Status: Frozen

ABSTRACT

Currently, using objects in numeric and string contexts is not very useful or easy:

   $r = new CGI;
   $z = $r + $x;      # oops
   print "$r\n";      # double-oops

You can use facilities such as tie to help fix this issue, but tie is limited and slow. You can also use overload, but this is not flexible enough for many applications since it applies to a package (and not individual objects).

This RFC proposes the concept of true polymorphic objects, which are objects that can morph into numbers, strings, booleans, and much more on-demand. As such, objects can be freely passed around and manipulated without having to care what they contain (or even that they're objects).

NOTES ON FREEZE

The only comments received were function additions. No real oppositions were recorded. As such, the functions have been added and the RFC frozen.

DESCRIPTION

Overview

The top-level syntax remains the same. As such, transition to Perl 6 is very smooth for most people, and in fact most users don't have to care about any of the following details. To them, this script will "just work":

   $y = Math->data(7); 
   $x = 3;
   $name = getname("Nate");
   if ( $x < 5 ) {
      $y += $x;
      if ( ! $name ) {
         $name = "The math whiz";
      }
   }
   print "$name got $y";   # "Nate got 10"

However, under the hood things might work drastically differently. In fact, $y and $name might well be polymorphic objects:

   $y = Math->data(7);          # $y = Math->data; $y->STORE(7)
   $x = 3;                      # $x = 3
   $name = getname("Nate");     # $name = getname; $name->STORE("Nate")
   if ( $x < 5 ) {              # $x < 5
      $y += $x;                 # $y->STORE($y->PLUS($x))
      if ( ! $name ) {          # $name || $name->BOOLEAN
        $name = "The math whiz";# $name->STORE("...")
      }
   }
   print "$name got $y";        # $name->STRING , $y->STRING

Here, $y and $name are objects, but we don't have to care. These objects have a key property: context sensitivity. They have numerous different methods which are each called only in specific instances. So, being called in a numeric context calls NUMBER, whereas being called in a string context would call STRING.

Plus, operators are overloadable as well. This means that we might decide to overload + to become a Java-like concatenation operator on our objects:

   $string = $name + "Wiger";   # $name->PLUS("Wiger")

Yuck. :-) But it can be done, and that's pretty cool.

Polymorphic Methods

The following are the proposed methods for Perl 6 objects. Note that these methods are completely optional for a class to define. If they are not defined, the object would retain its current behavior. The hooks are in Perl if you want them, otherwise they don't get in the way.

Note that STRING, NUMBER, and BOOLEAN are specialized forms of FETCH. If you define them, they are used instead of FETCH in the given context, otherwise FETCH is used. Also note that the operators, when overloaded, behave similarly to 'use overload', but on an object by object basis, rather than package-wide.

Alternative names are listed in parens.

   Data Conversion and Access
   -------------------------------------------------
   STRING           Called in a string context
   NUMBER           Called in a numeric context
   BOOLEAN          Called in a boolean context


   Operator Overloading
   -------------------------------------------------
   PLUS     (ADD)   Called in + context
   MINUS    (SUB)   Called in - context
   TIMES    (MUL)   Called in * context
   DIVIDE   (DIV)   Called in / context
   MODULUS  (MOD)   Called in % context
   CONCAT           Called in . context

   NUMCMP           Called in <=> context 
   NUMEQ            Called in == context
   NUMNE            Called in != context
   NUMLT            Called in <  context
   NUMGT            Called in >  context
   NUMLE            Called in <= context
   NUMGE            Called in >= context

   STRCMP           Called in cmp context
   STREQ            Called in eq context
   STRNE            Called in ne context
   STRLT            Called in lt context
   STRGT            Called in gt context
   STRLE            Called in le context
   STRGE            Called in ge context

   BITAND           Called in & context
   BITOR            Called in | context
   BITXOR           Called in ^ context
   BITNOT           Called in ~ context

   LOGNOT           Called in ! context
   LOGHIGHAND       Called in && context
   LOGHIGHOR        Called in || context
   LOGLOWAND        Called in and context
   LOGLOWOR         Called in or context
   LOGIFELSE        Called in ?: context


   Operator Fallbacks (like 'use overload')
   -------------------------------------------------
   OVERLOAD         Like an AUTOLOAD for the above,
                    perhaps NOMETHOD is a better name


   Assignment and Existence
   -------------------------------------------------
   CREATE           Called in variable creation (?)
   BUILD            Called in object blessing
   REBUILD          Called in object reblessing
   STORE            Called in an lvalue = context
   FETCH            Called in an rvalue = context
   DESTROY          Called in object destruction

There are undoubtedly other functions that should be added. However, the purpose of this RFC is to propose an idea and a basic interface. [1]

Now, whether the word TIMES is better than MUL is debateable. I was trying to get the English verb context right, sticking with words:

   $x * $y     # $x->TIMES($y)

Which I think makes the function names intuitive and easy to remember. I left out any potential _'s because these are a pain to type, and no other Perl builtins have them.

The CREATE method may or may not serve to be useful; there is some debate about what it could do since the true creation of an object occurs on blessing, not on variable declaration. With embedded objects it could well serve to prepare the object, optimizing storage space and tinkering with internals. However, without embedded objects it is probably of dubious usefulness. For more details and discussion on this particular issue, please see RFC 189: Hierarchical calls to initializers and destructors.

IMPLEMENTATION

Fundamental hooks would have to be put into Perl in order to look for these subs for the corresponding operations. Since it looks like -internals will probably put vtable stuff in SV from the get-go, this could potentially not be that tricky. At compile-time, Perl could simply look for these subs in a class definition and create the proper hooks for overloading, similar to how 'use overload' works now but at a lower level.

Note that the OVERLOAD method serves a simliar purpose to AUTOLOAD and the nomethod tag in overloading. If it exists, then it is used to fallback for non-overloaded operations. Otherwise, the overloading behavior is automatically determined by Perl. Perl should make these decisions in UNIVERSAL::OVERLOAD, so that the user can defer to it in their own OVERLOAD method if need be.

MIGRATION

This introduces new functionality, however p52p6 would have to catch any subs defined with the names listed above and warn the user that this sub name is now reserved for Perl.

Worth consideration with the proliferation of ALLCAPS methods and variables is whether a warning like this:

   ALLCAPS sub name may conflict with future reserved word at line 3.

Might not be worth spitting out if a user defines a sub in ALLCAPS that is not a recognized special Perl sub. This RFC does not take a stand on this issue but rather provides it for consideration.

NOTES

[1] Abiding by the KISS property (Keep It Simple, Stupid)

REFERENCES

RFC 189: Hierarchical calls to initializers and destructors

RFC 49: Objects should have builtin stringifying STRING method

RFC 73: All Perl core functions should return objects

Perl's existing use overload and tie

www.mail-archive.com

ACKNOWLEDGEMENTS

Thanks to brian d foy and Damian Conway for their input

Thanks to Uri Guttman for suggesting CREATE on a different topic

Thanks to David Nicol for his suggestion of BOOLEAN