RFC 161 (v2) OO Integration/Migration Path
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE OO Integration/Migration Path =head1 VERSION Maintainer: Matt Youell [EMAIL PROTECTED] Date: 25 Aug 2000 Last Updated: 27 Aug 2000 Mailing List: [EMAIL PROTECTED] Version: 2 Number: 161 =head1 ABSTRACT Allow Perl 6 to benefit more directly from object orientation and object syntax while leaving a bridge to Perl 5. =head1 DESCRIPTION =head2 Overview Everything in Perl becomes an object, using existing object-syntax. Out of plain sight, there would be essentially three base classes: Scalar, List, and Hash. Stricter typing would be imposed (as needed) at the object level without the need for new keywords. The Scalar base class would know about a fixed number of types, perhaps: ref, int, long, bool, and string. Other types could be added by subclassing Scalar. =head2 Examples For example, rather than: my int $intVal = 0; you would say: my $intVal = 0; $intVal-asInt; Or possibly even: my $invVal-asInt = 0; for simplicity. Unary operations could also be made the Scalar object's responsibility in the same style: $record-chop; Or even possibly controversial things like: $value-undef; Finally, some of the more domain-specific features being requested of the language could be added in a subclass of Scalar. For example, transaction-friendly variables might be subclassed: use Transactions; my $firstName = "Bob"; # ... (transaction happens) ... $firstName-commit; # or -rollback (Of course, transaction vars might be in their own, independent, class ala TMTOWTDI.) =head2 Wrap-up What this gives us is a means for adding functionality while leaving the basic language structure alone. This way we don't interfere with improvements happening elsewhere in the language, and we leave a clean migration path for Perl 5. Also, by allowing lower-level extensibility, many language-feature requests may become moot. =head1 IMPLEMENTATION Most of the tools required to implement this system are already there. - Scalar values already have Perl Doing The Right Thing for type conversion. Providing the user with methods to activate type conversion explicitly shouldn't be a major chore. In fact it could lighten Perl's load in many cases by eliminating guess work about when to convert. - The existing bless-based object system provides most (if not all) of the tools needed to implement this system. For example, if I create my own scalar class in Perl 5, I can say: $myScalar-chop; or chop $myScalar; and Perl automagically knows what I mean, barring namespace considerations. It could work the same way in Perl 6. That would mean that older code could very easily get along with newer code, because all of the same operators would still be there and they would still work as expected. =head1 MISC This approach may also allow for better organization of Perl's internals, specifically if the plan is to move toward a Topaz-style (C++) implementation. Also, by organizing responsibilities into explicit classes, the "mind-reading" load might lighten for the Perl interpreter. At least it looks that way from outside. =head1 REFERENCES RFC 4: "Type Inference" RFC 35: "A proposed internal base format for perl variables" RFC 49: "Objects should have builtin stringifying STRING method" RFC 89: "Controllable Data Typing" RFC 137: "Overview: Perl OO should Inot be fundamentally changed." (specifically the EXECUTIVE SUMMARY) http://www.perl.com/pub/1999/09/topaz.html : "Topaz: Perl for the 22nd Century" - Chip Salzenberg http://www.youell.com/matt/perlstring/ - A C++ string class that emulates Perl's scalar manipulation tools. Bears some similarity to the Scalar object described here.
RFC 163 (v1) Automatic accessors for hash-based objects
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Automatic accessors for hash-based objects =head1 VERSION Maintainer: James Mastros [EMAIL PROTECTED] Date: 25 Aug 2000 Version: 1 Mailing List: [EMAIL PROTECTED] Number: 163 =head1 ABSTRACT This RFC proposes an attribute, C:accessible L[1] that may be applied to hash keys to make them accessible to the outside as C$obj-Egtfoo, this being (largely) equivalent to C$obj-Egt{foo}. =head1 DESCRIPTION The C:accessible attribute on a hash key L[2] would make it such that, given a blessed hashref C$obj, C$obj-Egtfoo can refer to the same variable as C$obj-Egt{foo}. Note that I say "can", because whether or not it Iwill depends on the parameters to the accessible attribute. The phrase $obj-Egtfoo will be referred to as an accessor for the rest of this document, and an autoaccessor if it is not a real method, but emulated via the :accessible mechanism. The value part of the hash element that defines the autoaccessor is called the autoaccessor's value. If the call to an autoaccessor is in list context, it returns the single-element list containing the value of the key, just as C$obj-Egt{foo} would. This means that it is impossible for an autoaccessor to ever return a list (it can return an arrayref, though). This hopefully isn't a problem. If the attribute has parameters, each can be a context-permission specifier, or a meta-attribute. A context-permission parameter consists of an optional permission, followed by an access type, a sequence which can repeat zero or more times. The permissions are: The defined permissions are: '!', which forces the method call to fail, without further ado L[5], and '+', which makes the autoaccessor handle the call '~', which makes the autoaccessor fail, but allow traditional ways of handling the method call.. The default is '+', if no permission is specified for a context. A context with a '~' permission is the same as not specifying the context letter at all L[7], and is included only for completeness. The context can be: 'r' for rvalue (or 'r' for read) 'l' for lvalue (or 'w' for write) 'm' for mutator (which has no synonym) L[6] If a letter is not present, use of the autoaccessor does not occur in this context, but normal subs, AUTOLOAD, and inheritance are all tried. The letters attempt to be mnemonic with both the computer science terms and the analogous file permissions. The exception to this is that if the attribute is present, but has no arguments, the default is '+r', that is the autoaccessor is used for read access only, but mutate and write access must be through a written lvalue sub L[7] L[8]. In addition, there is one defined meta-attributes, which change the way in which the autoaccessor determines the value to return. (Note that these cannot be concatenated to the permission specs or to each-other.) The first is "list", which tells the autoaccessor that in list context, it should deref its value, and then return it. Without this, the autoaccessor will return the ref itself, even in list context. L[9] =head1 IMPLEMENTATION Here is one possible method, which does require changes to core (or possibly transparent ties). Whenever this attribute is set on a hash key, an attribute (C:has_accessible_keys) is set on the hash. Whenever method lookup fails on an object that is a hashref, the hash would be checked for the C:has_accessible_keys attribute and, if found, a lookup for the key in the thingy would occur. If it is found, and the :accessible attribute is found, the parameter of the attribute would be checked, and it is processed as in DESCRIPTION above. The attribute on the hash is there on the assumption that it's much faster then a key lookup. This might not be the case. =head1 DIAGNOSTICS =begin perldiag =item call to method "%s" in class %s denied by autoaccessor permissions (F) You attempted to call an autoaccessor in a context it didn't like. This probably means that it's impossible to do this (or the permissions are wrong). Check the documentation of the class mentioned. =end perldiag The first %s should be the method name, and the second should be ref($obj). =begin perldiag =item Autoaccessor '%s' attempted to deref nonref '%s'. (F) The autoaccessor is set up to autoderef it's value, but it's value isn't a ref. This is probably the fault of the module writer. =end perldiag The first %s is the name of the autoaccessor, the second is it's value. =head1 EXAMPLES This example shows how much easier it would have been to write the example on line 170 of perltoot.pod: package Person; use strict; ## ## the object constructor (simplistic version) ## ## sub new { my $self = {}; $self-{name} :accessible('rw') = undef; $self-{age} :accessible('rw')
RFC 193 (v1) Objects : Core support for method delegation
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : Core support for method delegation =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 4 September 2000 Mailing List: [EMAIL PROTECTED] Version: 1 Number: 193 Status: Developing =head1 ABSTRACT This RFC proposes that Perl 6 offer built-in support (via a pragma) for delegating method calls to attributes of an object. =head1 DESCRIPTION Delegation of method calls to attributes is a powerful OO technique that is not well supported in most OO-capable languages, including Perl 5. Delegation offers most of the advantages of inheritance (and, more particularly, multiple inheritance) without most of the headaches. It also offers some extra features that inheritance cannot provide. The proposed delegation mechanism would work via a pragma: use delegation attr1 = [qw( method1 method2 method3 )], attr2 = [qw( method4 method5 )], attr3 = [], attr4 = [], # etc. ; This would cause method calls whose names match an element in the first list to be delegated to the "attr1" attribute of an object. Likewise, calls to a method whose name appears in the second list would be forwarded to the "attr2" attribute of the object. That is, calls like: $obj-method3(@args); $obj-method5(@other_args); would act as if they were: $obj-{attr1}-method3(@args); $obj-{attr2}-method5(@other_args); (and, if these attribute objects also delegated, the process might repeat recursively until some deeply nested attribute actually provided a method to call). Attributes which appear in with an Iempty method list become "catch-alls". Unresolvable method calls are delegated to the first of these that is able to handle it. So, for example, a call like: $obj-method6(@more_args); would become equivalent to: $obj-{attr3}-method6(@more_args); if $obj-{attr3} had a Cmethod6 method (or an CAUTOLOAD), or else: $obj-{attr4}-method6(@more_args); if $obj-{attr4} had a suitable method. Unlike explicitly delegated methods, which are delegated on the first method look-up pass, delegation to catch-alls occurs on the second pass, just before the dispatch mechanism tries the package's CAUTOLOAD method. Note that the presence of one or more catch-all's does not prevent an CAUTOLOAD being called, if none of the catch-alls can handle the requested method. If the explicit methods, the catch-alls (and any CAUTOLOAD) all fail to provide a suitable method, the normal dispatch would then continue into the object's ancestral classes (if any). An attribute can appear several times in a Cuse delegation statement, with all its delegation method lists being consolidated. An attribute may also appear with an explicit delegation list and as a catch-all. For example: use delegation attr1 = [qw(method1 method2)], attr2 = [qw(method3 method4)], attr1 = [], ; This example specifies that calls to the methods Cmethod1 and Cmethod2 should be delegated to the "attr1" attribute, calls to the methods Cmethod3 and Cmethod4 should be delegated to the "attr2" attribute, and any remaining calls that are not handled before the CAUTOLOAD pass should be delegated to the "attr1" attribute (if it can handle them). =head2 New dispatch sequence With delegation available, the method dispatch sequence becomes (Ichanges from Perl 5 mechanism in italics): =over 4 =item 1. Look for the named method in current class, Ichecking for explicitly delegated methods as well. =item 2. Recursively repeat steps 1 and 2 in ancestral class(es) and in UNIVERSAL. =item 3. ICheck for implicitly delegated methods through catch-all attributes. These may be explicit or CAUTOLOADed in the attribute object's class. =item 4. Check for CAUTOLOAD in current class =item 5. Recursively repeat steps 3 to 5 in ancestral class(es) and in UNIVERSAL. =back =head2 Using delegation instead of inheritance One powerful application of delegation is as a replacement for inheritance where the internals of a prospective base class are inaccessible or inconvenient, or the base class was not designed to be inherited and yet it must be. For example, consider the task of creating an IO::File-like class that reads and writes to separate handles: use IO::Bi; my $handle = IO::Bi-new('infile', 'outfile'); if (defined($_ = $handle-getline)) { $handle-print($_); } foreach ($handle-getlines) { $handle-print($_); } IO::Bi can't inherit from IO::File, because it needs two file handles, with input methods going to one and output methods going to the other. That's impossible with inheritance (even using the dreaded "diamond inheritance pattern") because a class can inherit
RFC 161 (v3) Everything in Perl becomes an object.
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Everything in Perl becomes an object. =head1 VERSION Maintainer: Matt Youell [EMAIL PROTECTED] Date: 25 Aug 2000 Last Updated: 7 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 161 Version: 3 Status: Developing =head1 ABSTRACT Everything in Perl becomes an object, out of sight, but within easy reach. Perl stays Perlish. Syntax remains fundamentally the same; Perl 5 code migrates well. Previous versions of this RFC were entitled "OO Integration/Migration Path". =head1 DESCRIPTION =head2 Goals 1. Provide a more complete mechanism for extending the language. 2. Organize responsibilities closer to the corresponding data structures. 3. Maintain a compatibility bridge to Perl 5. =head2 Proposal Everything in Perl becomes an object, using (mostly) existing object-syntax. The built-in types $scalar, @list, and %hash become the extensible base classes Scalar, List, and Hash. New built-in data types (such as int, bool, string, etc.) are derived from Scalar. Regular "vanilla" $scalars don't go away, they are simply considered to be instances of Scalar. And like any $scalar, they still Do The Right Thing. =head2 Syntax "my Dog $spot" works under this model. Where a class is not provided, a default is deduced from context ($, @, %). For example: my $foo = "foo"; is equivalent to: my Scalar $foo = new Scalar("foo"); # (Or similar. This syntax is currently in discussion.) Methods would be called as they are for any object: $noun-verb(); or, indirectly: verb $noun; =head2 Extensibility By allowing Perl's built-in types to be extended, programmers can retain Perl's simple syntax while better fitting their particular problem domain. All without polluting the core language. For example, there has been discussion of adding transaction support to Perl. Rather than adding such support into the language directly, it could be added as a subclass of Scalar. This might work like so: use Transactions::Scalar; # This replaces the default scalar with a derived class. A detail needing exploration. my $firstName = "Bob"; # AKA: my Transactions::Scalar $firstName = new Transactions::Scalar("Bob"); # ... (transaction happens) ... commit $firstName; # or rollback $firstName Or, say that you wanted to override built-in behavior. Perhaps you want 'ord' to return numeric EBCDIC values. You can create your own 'ord' routine in your derived class and have it do that very thing. =head2 Conclusion This approach provides a means for adding functionality while leaving the basic language structure alone. It doesn't interfere with improvements happening elsewhere in the language, and it leaves a clean migration path for Perl 5 code. =head1 IMPLEMENTATION This RFC tries to present a user-interface view of how this feature would work. Other RFCs cover the specific nuts bolts approaches that are possible. =head1 REFERENCES RFC 137: Overview: Perl OO should Inot be fundamentally changed. (specifically the EXECUTIVE SUMMARY) RFC 159: True Polymorphic Objects http://www.youell.com/matt/perlstring/ - A C++ string class that emulates Perl's scalar manipulation tools. Bears some similarity to the Scalar object described here.
RFC 200 (v1) Objects: Revamp tie to support extensibility (Massive tie changes)
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects: Revamp tie to support extensibility (Massive tie changes) =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 07 Sep 2000 Mailing List: [EMAIL PROTECTED] Version: 1 Number: 200 Status: Developing Requires: RFC 159, RFC 174 =head1 ABSTRACT Ctie is really cool. Mostly. It has an amazing amount of power in concept, but suffers from several limitations which this RFC attempts to address. =head1 DESCRIPTION =head2 Overview Many people have expressed problems with tie, including Larry [1]. Ctie suffers from several limitations: 1. It is non-extensible; you are limited to using functions that have been implemented with tie hooks in them already. 2. Any additional functions require mixed calls to tied and OO interfaces, defeating a chief goal: transparency. 3. It is slow (at least slower than other objects) 4. You can't easily integrate tie and operator overloading. 5. If defining tied and OO interfaces, you must define duplicate functions or use typeglobs. 6. Some parts of the syntax are, well, kludgey This RFC attempts to address all of these points with some changes to syntax and implementation concepts. It interacts with the concept of Bpolymorphic objects, described in LRFC 159, to provide a simple and extensible framework. =head2 New Concepts This RFC proposes two key principles that will provide a more general-purpose Ctie framework: 1. Operator, data, and syntax overloading will be done via the ALLCAPS methods described in RFC 159. 2. All other functions are directly translated via the indirect object syntax. In addition, the declaration of a tie statement is suggested to be changed into a standard indirect object function: $object = tie Tie::Class @array_to_tie; The default Ctieing would be performed by CUNIVERSAL::tie, which would be a new method that properly "blessed" the tied variable and then simply turned around and called the class's CTIE method, similar to how the builtin Ctie works currently. There are many changes, so let's go through them one at a time and then revisit how they will all tie (ha-ha) together at the end. =head2 Syntax Changes =head3 Drop Ctie builtin and replace with CUNIVERSAL::tie As mentioned above, this allows us to call Ctie in a simple indirect object form. This eliminates one more special-case function which currently requires that quotes be placed around the class name. This syntax should simply be modified to be called on the object it will be tied to, since Ctie is after all an object constructor. =head3 Merge CTIESCALAR, CTIEHASH, and CTIEARRAY into CTIE In practice, people rarely make a class that Cties multiple data types through the same interface. The reason is that CSTORE, CFETCH, CDESTROY, and other methods overlap. As such, it is more feasible to create several different modules; witness CTie::Array, CTie::Scalar, CApache::Session, and other modules. =head3 Drop CTIEHANDLE Thanks to the below syntax, differentiating between filehandles and other scalars is no longer important. It would also be very difficult to make this distinction, since in Perl 6 filehandles are intended to be C$scalars. =head3 Continue to do data handling through ALLCAPS methods This will not change. CSTORE and CFETCH, along with other functions described in RFC 159 and below, will continue to do data handling. In addition, these methods will be used for operator overloading as well. =head3 Perform functions through the indirect object syntax Currently, Ctie incurs a fairly substantial overhead (depending on your application) because function calls such as this: push @tied_array, $value; Must be internally transformed into this: $self-PUSH($value); In addition, you are bound by the methods that the designers have implemented. While Perl 5.6 finally has a fairly substantial collection, nonetheless it is easy to imagine that future functions will arise which you want to Ctie, but which support has not been added for yet. Plus, if you want to support extra methods of your own, you must mix object and tied calls: $obj = tie %trans, 'Transaction'; $trans{$var} = $value; $obj-lock($var); Unfortunately, this defeats one of the key purposes of tie, which is OO transparency. And, creating a class that supports both OO and tied interfaces is difficult, requiring typeglobs or duplicate handler functions. Instead, this RFC proposes that Ctie's operation become much more fundamental, simply translating functions via the existing indirect object syntax: tie Transaction %trans;# indirect object constructor $trans{$var} = $value ;# $obj-STORE($var, $value); lock $trans{$var}; # $obj-lock($var); delete $trans{$var}; # $obj-delete($stuff); foo %trans;# $obj-foo; %trans = (); #
RFC 49 (v3) Objects should have builtin stringifying STRING method
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects should have builtin stringifying STRING method =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 06 Aug 2000 Last Modified: 14 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 49 Version: 3 Status: Frozen =head1 ABSTRACT Currently, $ single-whatzitz types in Perl can hold several different things. One of the things that these are commonly used to hold are objects, such as: $q = new CGI; $r = Apache-request; Unfortunately, there is no easy way to tell these are actually objects without lots of annoying ref checks throughout your code. So if you say: print "$q"; This prints out something like this: CGI=HASH(0x80ba4e8) Which isn't very useful. This RFC attempts to fix this by providing builtin special method CSTRING which is automatically called when an object is "stringified". While this can be accomplished through the use of 'use overload', a more automatic, object-specific method has certain advantages. For more details on this, please see RFC 159. =head1 NOTES ON FREEZE This RFC goes into details on the uses of CSTRING, but what you really want to read is LRFC 159: True Polymorphic Objects, which extends these concepts to other Perl operators and contexts. =head1 DESCRIPTION Currently, there is no way to easily distinguish between these two syntaxes: $scalar = date; # scalar ctime date, same as localtime() $object = date; # date object with accessor functions As such, there is no easy way to have the Cdate() function return both - it must decide what to return within the general scalar context. Damian's excellent RFC 21 on Cwant() addresses several specific cases, several have suggested alternate syntaxes, such as: my Date $object = date; # return object of class 'Date' my tm $object = date; # return object of struct 'tm' However, this doesn't solve the problem, since printing out either of these in a scalar context still results in "garbage". I suggest that objects provide a default method called CSTRING that determines what they produce in a string context. When stringified, an object would automatically call its CSTRING function and return the correct value. For example, RFC 48 describes a new Cdate() interface. In a scalar context, it could produce a date object always: $date = date; However, when you went to do anything with it in a string context, it would call the appropriate method: print "$date"; # calls $date-STRING, which in this case would # print out a ctime formatted date string The call to C$object-STRING would be a decision made by Perl, similar to the way that Ctie() works. The object simply has to provide the method; Perl does the rest. This gives us several other really neat side effects. First, we can now return a list of objects and have them act the same as a "regular old list": (@objects) = Class-new; Since, in a stringifying context, each of these objects would call their CSTRING methods: print "@objects"; # calls $objects[0]-STRING, $objects[1]-STRING, # and so on for the whole array, thus making it # look like a plain old list As such, we no longer have to distinguish between objects and "true" scalars. Objects are automatically converted when appropriate. =head1 IMPLEMENTATION All core objects should be modified to include a CSTRING function. This function may just be a typeglob pointing to another function, or it may be an actual separate function. Hooks will have to be put in Perl's string context so that if something is an object, then that object's CSTRING method is called automatically if it exists. =head1 MIGRATION None. This introduces new functionality. =head1 REFERENCES RFC 159: True Polymorphic Objects RFC 21: Replace wantarray with a generic want function RFC 48: Replace localtime() and gmtime() with date() and utcdate() Lots of people on perl6-language for great input, thanks!
RFC 222 (v1) Interpolation of method calls
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Interpolation of method calls =head1 VERSION Maintainer: Michael G Schwern [EMAIL PROTECTED] Date: 14 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 222 Version: 1 Status: Developing =head1 ABSTRACT Method calls should interpolate in double-quoted strings, and similar locations. print "Today's weather will be $weather-temp degrees and sunny."; Would deparse to: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; =head1 DESCRIPTION =head2 The Current Problem With OO Interpolation Object-oriented programming encourages data-hiding, and one of the most basic tool for this is the accessor method. For reasons which should be obvious, C$obj-foo() is usually better than C$obj-{foo}. However, there are several barriers to using an accessor method as simply as one does a hash lookup. Other RFCs deal with most of the current issues, but a basic one still remains. print "Today's weather will be $weather-temp degrees and sunny."; This does not DWIM. Instead of interpolating C$weather-temp as a method call, it comes out as C$weather.'-temp' and is usually followed immediately by the question "What does 'Weather=HASH(0x80d4174)-temp' mean??" Most programmers learning OO Perl expect this to work and are surprised to find that it does not. Work arounds abound: # If I wanted printf(), I'd have written it in C. printf "Today's weather will be %d degrees and sunny.", $weather-temp; my $temp = $weather-temp; print "Today's weather will be $temp degrees and sunny."; print "Today's weather will be @{[$weather-temp]} degrees and sunny."; print "Today's weather will be ".$weather-temp." degrees and sunny."; None are as simple and as obvious as: print "Today's weather will be $weather-{temp} degrees and sunny."; and because of this users groan at having to use accessor methods and are often tempted to violate encapsulation for ease of use. =head2 Proposed Solution - Interpolate Methods Therefore, it is proposed that direct object method calls be interpolated inside double quoted strings and similar constructs. print "Today's weather will be $weather-temp degrees and sunny."; should parse out as: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; thus returning DWIMness to methods and strings and removing one barrier to accessor method's acceptance over hash lookups for objects. Methods will be run in scalar context. A method which returns a single scalar is treated normally. If a list is returned, it should be treated same as array interpolation. The list seperator will be applied. In effect, the deparsing will really work out as follows: print 'Today\'s weather will be '.join($", $weather-temp()). ' degrees and sunny.'; However if temp() calls wantarray(), the result will be FALSE (scalar). (For the remainder of the RFC, the join() will be assumed when discussing deparsing for brevity.) Should it be decided that a formal distinction be made between accessor methods and other types (RFC 95), method interpolation should interpolate Bany method. =head2 Argument passing Interpolation should also handle passing arguments to methods in a string: print "Today's weather will be $weather-temp("F") degrees and sunny."; This should deparse to: print 'Today\'s weather will be '.$weather-temp("F"). ' degrees and sunny.'; The arguments to the method are considered as normal expressions, thus: print "There is $obj-foo(this = $yar, that = 2 + 2) in my head."; deparses as: print 'There is '.$obj-foo(this = $yar, that = 2 + 2). ' in my head."; =head1 CAVEATS Indirect object syntax, being already ambiguous, cannot be easily be distinguished in a string from normal text and should not be interpolated. This is ok, since accessors are rarely called with indirect object syntax. Are there any contexts besides double quotes ("", qq{}, "EOF") where this need be applied? What about inside regexes? And if so, left and/or right hand side? Normally, whitespace is allowed between tokens of a method call. $obj - bar ("this"); and $obj-bar("this"); are equivalent. Whitespace between the object, '-', method name and opening paren should be disallowed when interpolated. This will avoid many ambiguous cases. Should the method not exist, Perl will throw an exception/die as usual. C"$var-{this}[2]{is}-{complex}-method" should also be interpolated. Also C"$obj-method-{key}" for the case where a method returns a reference. =head1 IMPLEMENTATION The behavor of the parser to check for embedded variables would have to be altered, namely the case where an embedded variable is being dereferenced. A case would be added to allow method calls as well as hash and array index dereferences. Otherwise, parsing should remain as normal. =head1
RFC 189 (v2) Objects : Hierarchical calls to initializers and destructors
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : Hierarchical calls to initializers and destructors =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 1 September 2000 Mailing List: [EMAIL PROTECTED] Number: 189 Version: 2 Status: Developing =head1 ABSTRACT This RFC proposes a new special method called CBUILD that is invoked automagically whenever an object is created. Furthermore, it proposes that both CBUILD and CDESTROY methods should be invoked hierarchically in all base classes. =head1 DESCRIPTION One of the major limitations of object-oriented Perl is that, unlike most other OO languages, it does not automatically invoke the initializers and destructors of base classes, when initializing or destructing an object of a derived class. This leads to tediously complex code in constructors and destructors in order to manually achieve the same effect. More often, it leads to bugs. It is proposed that Perl 6 introduce an automatic object initialization mechanism, analogous to the automatic object clean-up mechanism provided by CDESTROY methods. It is further proposed that both the initialization and destruction mechanisms automatically call their corresponding base class versions to ensure that complete initialization and destruction of derived objects occurs correctly. =head2 The CBUILD method It is proposed that, if a class has a method named CBUILD, that method will be invoked automatically during any call to Cbless. It is further proposed that Cbless be extended to take an optional argument list after its second argument, and that this list would be passed to any CBUILD method invoked by the Cbless. The typical constructor would then be reduced to: package MyClass; sub new { bless {}, @_ } with initialization handled in a separate CBUILD routine: sub BUILD { my ($self, @ctor_data) = @_; # initialization of object referred to by $self occurs here } =head2 Hierarchical CBUILD calls It is proposed that when an object is blessed, Iall of the CBUILD methods in any of its base classes are also called, and passed the argument list appended to the invocation of Cbless. CBUILD methods would be called in depth-first, left-most order (i.e. ancestral CBUILD methods would be called before derived ones). Any given CBUILD method would only be called once for the same object, no matter how many separate paths its class might be inherited through. For example, given the following class hierarchy: package Base1; sub new { bless {}, @_ } sub BUILD { print "Base1::BUILD : @_\n" } package Base2; sub BUILD { print "Base2::BUILD : @_\n" } package Base3; sub BUILD { print "Base3::BUILD : @_\n" } package Derived1; use base qw(Base1 Base2); sub BUILD { print "Derived1::BUILD : @_\n" } package Derived2; use base qw(Base2 Base3); sub BUILD { print "Derived2::BUILD : @_\n" } package Rederived1; use base qw(Derived1 Derived2); sub BUILD { print "Rederived1::BUILD : @_\n" } then the call to: $obj = Rederived-new(1..3) would print: Base1::BUILD : 1 2 3 Base2::BUILD : 1 2 3 Derived1::BUILD : 1 2 3 Base3::BUILD : 1 2 3 Derived2::BUILD : 1 2 3 Rederived1::BUILD : 1 2 3 Note in particular that CBase2::BUILD is only called once (as early as possible), even though class Rederived inherits it through two distinct paths. =head2 Hierarchical CDESTROY calls It is further proposed that when an object's destructor is invoked, all inherited destructors would also be invoked, in depth-Ilast, right-most order. Again, each CDESTROY for an object would be called exactly once, regardless of how many different paths it is inherited through. For example, given the following class hierarchy (with the same topology as the example for CBUILD above): package Base1; sub new { bless {}, @_ } sub DESTROY { print "Base1::DESTROY\n" } package Base2; sub DESTROY { print "Base2::DESTROY\n" } package Base3; sub DESTROY { print "Base3::DESTROY\n" } package Derived1; use base qw(Base1 Base2); sub DESTROY { print "Derived1::DESTROY\n" } package Derived2; use base qw(Base2 Base3); sub DESTROY { print "Derived2::DESTROY\n" } package Rederived1; use base qw(Derived1 Derived2); sub DESTROY { print "Rederived1::DESTROY\n" } then the destruction of an object: $obj = "something else"; would print: Rederived1::DESTROY Derived2::DESTROY Base3::DESTROY Derived1::DESTROY Base2::DESTROY Base1::DESTROY Note that CBase2::DESTROY is only called once (as late as
RFC 224 (v1) Objects : Rationalizing Cref, Cattribute::reftype, and Cbuiltin::blessed
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : Rationalizing Cref, Cattribute::reftype, and Cbuiltin::blessed =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 14 September 2000 Mailing List: [EMAIL PROTECTED] Number: 224 Version: 1 Status: Developing =head1 ABSTRACT This RFC proposes that rather than three separate mechanisms (in three separate namespaces) to determine object typing information, Perl 6 simply extend the Cref function to return all the necessary information in a list context. =head1 DESCRIPTION In Perl 5, the class into which an object is blessed is returned by calling Cref on a reference to that object. To determine the underlying implementation type of the object, Cattribute::reftype is used. To determine whether or not a reference refers to a blessed object, builtin::blessed is used. It is proposed that the behaviour of Cref be altered in Perl 6 so that in a list context it returns up to two values: the underlying implementation type of the object (always returned), and the class into which the object is blessed (only if the object Iis blessed). Thus: if (builtin::blessed $ref) { $type = attribute::reftype $ref; $class = ref $ref; } else { $type = ref $ref; $class = "no class"; } print "Object of type $type, blessed into $class\n"; Would become: ($type, $class) = ref($ref); $class ||= "no class"; print "Object of type $type, blessed into $class\n"; =head1 MIGRATION ISSUES All existing calls to Cref in a list context would have to be translated to Cscalar ref. =head1 IMPLEMENTATION Trivial. =head1 REFERENCES None.
RFC 222 (v1) Interpolation of method calls
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Interpolation of method calls =head1 VERSION Maintainer: Michael G Schwern [EMAIL PROTECTED] Date: 14 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 222 Version: 1 Status: Developing =head1 ABSTRACT Method calls should interpolate in double-quoted strings, and similar locations. print "Today's weather will be $weather-temp degrees and sunny."; Would deparse to: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; =head1 DESCRIPTION =head2 The Current Problem With OO Interpolation Object-oriented programming encourages data-hiding, and one of the most basic tool for this is the accessor method. For reasons which should be obvious, C$obj-foo() is usually better than C$obj-{foo}. However, there are several barriers to using an accessor method as simply as one does a hash lookup. Other RFCs deal with most of the current issues, but a basic one still remains. print "Today's weather will be $weather-temp degrees and sunny."; This does not DWIM. Instead of interpolating C$weather-temp as a method call, it comes out as C$weather.'-temp' and is usually followed immediately by the question "What does 'Weather=HASH(0x80d4174)-temp' mean??" Most programmers learning OO Perl expect this to work and are surprised to find that it does not. Work arounds abound: # If I wanted printf(), I'd have written it in C. printf "Today's weather will be %d degrees and sunny.", $weather-temp; my $temp = $weather-temp; print "Today's weather will be $temp degrees and sunny."; print "Today's weather will be @{[$weather-temp]} degrees and sunny."; print "Today's weather will be ".$weather-temp." degrees and sunny."; None are as simple and as obvious as: print "Today's weather will be $weather-{temp} degrees and sunny."; and because of this users groan at having to use accessor methods and are often tempted to violate encapsulation for ease of use. =head2 Proposed Solution - Interpolate Methods Therefore, it is proposed that direct object method calls be interpolated inside double quoted strings and similar constructs. print "Today's weather will be $weather-temp degrees and sunny."; should parse out as: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; thus returning DWIMness to methods and strings and removing one barrier to accessor method's acceptance over hash lookups for objects. Methods will be run in scalar context. A method which returns a single scalar is treated normally. If a list is returned, it should be treated same as array interpolation. The list seperator will be applied. In effect, the deparsing will really work out as follows: print 'Today\'s weather will be '.join($", $weather-temp()). ' degrees and sunny.'; However if temp() calls wantarray(), the result will be FALSE (scalar). (For the remainder of the RFC, the join() will be assumed when discussing deparsing for brevity.) Should it be decided that a formal distinction be made between accessor methods and other types (RFC 95), method interpolation should interpolate Bany method. =head2 Argument passing Interpolation should also handle passing arguments to methods in a string: print "Today's weather will be $weather-temp("F") degrees and sunny."; This should deparse to: print 'Today\'s weather will be '.$weather-temp("F"). ' degrees and sunny.'; The arguments to the method are considered as normal expressions, thus: print "There is $obj-foo(this = $yar, that = 2 + 2) in my head."; deparses as: print 'There is '.$obj-foo(this = $yar, that = 2 + 2). ' in my head."; =head1 CAVEATS Indirect object syntax, being already ambiguous, cannot be easily be distinguished in a string from normal text and should not be interpolated. This is ok, since accessors are rarely called with indirect object syntax. Are there any contexts besides double quotes ("", qq{}, "EOF") where this need be applied? What about inside regexes? And if so, left and/or right hand side? Normally, whitespace is allowed between tokens of a method call. $obj - bar ("this"); and $obj-bar("this"); are equivalent. Whitespace between the object, '-', method name and opening paren should be disallowed when interpolated. This will avoid many ambiguous cases. Should the method not exist, Perl will throw an exception/die as usual. C"$var-{this}[2]{is}-{complex}-method" should also be interpolated. Also C"$obj-method-{key}" for the case where a method returns a reference. =head1 IMPLEMENTATION The behavor of the parser to check for embedded variables would have to be altered, namely the case where an embedded variable is being dereferenced. A case would be added to allow method calls as well as hash and array index dereferences. Otherwise, parsing should remain as normal. =head1
RFC 137 (v2) Overview: Perl OO should Inot be fundamentally changed.
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Overview: Perl OO should Inot be fundamentally changed. =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 21 Aug 2000 Last Modified: 18 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 137 Version: 2 Status: Frozen =head1 ABSTRACT This RFC proposes that the OO model and mechanisms present in Perl 5 Inot be changed significantly in Perl 6. It provides an overview of a suite of forthcoming RFC proposals that will provide the features, convenience, and safety that are missing from Perl 5, without compromising the essential flexibility of the existing Perl OO model. =head1 EXECUTIVE SUMMARY It ain't broken. Don't fix it. =head1 DESCRIPTION Perl's current OO model has a number of well-known deficiencies: lack of (easy) encapsulation, poor support for hierarchical method calls (especially constructors and destructors), limited (single) dispatch mechanism, poor compile-time checking. More fundamentally, many people find that setting up reliable OO class hierarchies requires too much low-level coding. But these very deficiencies are also Perl's great strength, compared to other, more restrictive, OO languages. The non-prescriptive, non-proscriptive nature of Perl's OO model makes it possible to construct am enormous range of OO systems within the one language: from archetype-based classless OO (Class::Classless), to formal Design-By-Contract models (Class::Contract). Effectively, Perl's OO mechanism spans the range of metaphors from Self to Eiffel -- an astonishing achievement. It is proposed that modules like Class::Classless, Class::Struct, and Class::Contract continue to be the preferred method of constraining and simplifying the creation of Perl classes, and that a better range of such modules (at very least, Class::Contract) be included in the standard distribution. To deal with the existing deficiencies without losing the remarkable power, I intend to propose the following extensions to OO Perl: =over 4 =item * A Cprivate keyword that lexically scopes hash keys to the current package, and allows hashes to contain two or more identically named (but differently scoped) entries. This would solve the problem of encapsulation in OO Perl for the vast majority of (predominantly hash-based) class structures. =item * A new special subroutine name -- CSETUP -- to separate construction from initialization. CSETUP methods would be automatically -- and hierarchically -- called whenever an object is created. =item * Changes to the semantics of Cbless so that, after associating an object with a class, the class's CSETUP methods are automatically called on the object. An additional trailing C@ parameter for Cbless, to allow arguments to be passed to CSETUP methods. =item * Changes to the semantics of DESTROY, so that all inherited destructors are, by default, automatically called when an object is destroyed. =item * Pre- and post-condition specifiers, which associate code blocks with particular subroutine/method names. These blocks would be automatically called before and after the subroutine/method of the same name, and trigger an exception on failure. For methods, pre- and post-conditions would be inherited and called hierarchically (with disjunctive short-circuiting, in the case of post-conditions). =item * Class invariant specifiers, which associate code blocks with a particular package/class. These blocks would be called automatically after the the execution of subroutine/method of the same name, and trigger an exception on failure. For methods, invariants would be inherited and called hierarchically. =item * Optional, configurable, multiple dispatch of methods, based upon typed parameters. =item * A CNEXT pseudo-class, enabling resumption of the dispatch search from within an invoked method, as well as the "rejection" of invocation (e.g. by an CAUTOLOAD). =item * Constraints on lexical variables such that Cmy Dog $spot can only be assigned a value $v if C$v-isa('Dog'). =item * An optional constraint (Cuse strict 'objvars'?), making it a fatal error to store a object reference in a non-typed lexical. =item * A new pragma -- Cdelegation -- that would modify the dispatch mechanism to automatically delegate specific method calls to specified attributes of an object. =back Collectively these extensions would significantly reduce the amount of code required to construct safe OO classes, whilst leaving available the existing "unconstrained" OO model where it might be needed. There will also be one additional -- and far more radical -- proposal that does not form part of the above suite. It would greatly enhance the reusability of OO Perl software, but at the cost of existing flexibility and greater migration effort. The proposal is: =over 4 =item * That in Perl 6, only hashes (and perhaps pseudohashes) may be blessed. =back This would result in no loss of
RFC 190 (v2) Objects : NEXT pseudoclass for method redispatch
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : NEXT pseudoclass for method redispatch =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 1 Sep 2000 Last Modified: 18 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 190 Version: 2 Status: Frozen =head1 ABSTRACT This RFC proposes a new pseudoclass named CNEXT. This pseudoclass would provide a way of correctly redispatching a method or an autoloaded method. =head1 DESCRIPTION Perl 5 provides a pseudoclass named CSUPER that allows a method to redispatch a call to the next available method in one of its parent classes. This redispatch mechanism works by searching for an inherited method in any of the ancestors of the Icurrent package (but not necessarily the invocant's package). This works well in many cases, but not when the next most appropriate method is actually in a sibling class of the current package, rather than in an ancestor. For example, consider invoking a debugging method named Cdump_info on a derived class object: $obj-dump_info(); In order to ensure that all the object's ancestral information was also dumped, its Cdump_info method might be structured like so: package Derived; use base qw(Base1 Base2); sub dump_info { my ($self) = @_; $self-SUPER::dump_info(); print $self-{derived_info}; } The various ancestral classes would then be structured similarly: package Base1; use base qw(GrandBase1); sub dump_info { my ($self) = @_; $self-SUPER::dump_info(); print $self-{base1_info}; } package Base2; use base qw(GrandBase2 GrandBase3); sub dump_info { my ($self) = @_; $self-SUPER::dump_info(); print $self-{base2_info}; } # etc. Unfortunately, this does not result in the derived object's complete information being dumped, since each call to CSUPER::dump_info will only call a single (left-most) ancestral Cdump_info. Thus only the Cdump_info methods in the left-most inheritance branch will ever be called. What is required here is a mechanism to resume the Ioriginal dispatch process, rather than initiate a new one from the current point. It is proposed that Perl 6 provide a new pseudoclass -- CNEXT -- to facilitate exactly that. A method invocation in which the method name is explicitly qualified with CNEXT:: (e.g. C$self-NEXT::method(@args)) would cause the original dispatch that invoked the current method to be restarted and the next suitable method called. Another way of thinking of the effect of such a redispatch would be that it repeats the original dispatch of C$self-method(@args), but ignores all dispatch candidates until it has reached (and by-passed) the current method. Of course, the mechanism wouldn't actually be implemented in this inefficient manner. Note that, after the redispatch, control returns to the original method. =head2 Redispatch of CAUTOLOAD methods The CNEXT pseudoclass also solves the problem of how to allow CAUTOLOAD methods to "decline" to handle particular invocations. For example, with CNEXT it is possible to implement an CAUTOLOAD method that only handles method calls of the form Cget_... and Cset_... and is effectively invisible to any other method requests (which might then trigger other CAUTOLOADs elsewhere in the object's inheritance tree). The implementation would look like this: sub AUTOLOAD { $AUTOLOAD =~ s/.*:://; if ($AUTOLOAD =~ /^get_\w+$/) { # Handle getting... } elsif ($AUTOLOAD =~ /^set_\w+$/) { # Handle setting... } else { # Decline to handle, # passing the request on to someone else... shift-${\"NEXT::$AUTOLOAD"}(@_); } } Note that the same trick could be applied by any method, to selectively refuse certain invocations, handing them on to some other inherited method instead. For example: package IO::URL; use base 'IO::File'; sub open { my ($self, $filename, @args) = @_; if ($filename !~ /^(http|ftp):/) { $self-NEXT::open($filename, @args); } else { # Open URL... } } =head1 MIGRATION ISSUES None. =head1 IMPLEMENTATION Presumably it would be necessary to cache the dispatch stack until the dispatched method finishes executing. Alternatively, implementing the method dispatcher as a coroutine would make this very easy. =head1 REFERENCES Conway, IObject Oriented Perl, pp. 183-184. RFC 8: The AUTOLOAD subroutine should be able to decline
RFC 224 (v2) Objects : Rationalizing Cref, Cattribute::reftype, and Cbuiltin:blessed
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : Rationalizing Cref, Cattribute::reftype, and Cbuiltin:blessed =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 14 Sep 2000 Last Modified: 18 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 224 Version: 2 Status: Frozen =head1 ABSTRACT This RFC proposes that rather than three separate mechanisms (in three separate namespaces) to determine object typing information, Perl 6 simply extend the Cref function to return all the necessary information in a list context. =head1 DESCRIPTION In Perl 5, the class into which an object is blessed is returned by calling Cref on a reference to that object. To determine the underlying implementation type of the object, Cattribute::reftype is used. To determine whether or not a reference refers to a blessed object, builtin::blessed is used. It is proposed that the behaviour of Cref be altered in Perl 6 so that in a list context it returns up to two values: the underlying implementation type of the object (always returned), and the class into which the object is blessed (only if the object Iis blessed). Thus: if (builtin::blessed $ref) { $type = attribute::reftype $ref; $class = ref $ref; } else { $type = ref $ref; $class = "no class"; } print "Object of type $type, blessed into $class\n"; Would become: ($type, $class) = ref($ref); $class ||= "no class"; print "Object of type $type, blessed into $class\n"; =head1 MIGRATION ISSUES All existing calls to Cref in a list context would have to be translated to Cscalar ref. =head1 IMPLEMENTATION Trivial. =head1 REFERENCES None.
RFC 256 (v1) Objects : Native support for multimethods
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects : Native support for multimethods =head1 VERSION Maintainer: Damian Conway [EMAIL PROTECTED] Date: 18 September 2000 Mailing List: [EMAIL PROTECTED] Number: 256 Version: 1 Status: Developing =head1 ABSTRACT This RFC proposes that Perl natively support multiply dispatched subroutines (multimethods). =head1 DESCRIPTION Multimethods solve a class of problems in which objects of two or more hierarchies must interact polymorphically, but where the nature of the interaction is determined by the run-time type of Iboth (Iall) the objects. =head2 Theoretical model It is proposed that calls to certain (explicitly marked) subroutines be dispatched using a different mechanism from that used for regular Perl 5 subroutines, or that used for Perl 5 methods. These explicitly marked subroutines would share the same name, but provide unique parameter lists. Collectively all marked subroutines with the same name but different parameters lists would be known as a Imultimethod, with each individual subroutine known as a Ivariant of the multimethod. The new dispatch mechanism would look at the classes or types of each argument to the subroutine (by calling Cref on each) and determine the "closest" matching variant of the multimethod, according to the parameter types specified in the variants' parameter list. The result would subsume the behaviour of function overloading (e.g. in C++) but in a more sophisticated manner, since multimethods take the run-time inheritance relationships of each argument into account. Another way of thinking of the mechanism is that it would perform polymorphic dispatch on every argument of a multimethod, not just on the first. =head2 Defining multimethods A single variant of a multimethod would be defined by specifying a subroutine with a full parameter list (as per RFC 128), and appending the attribute C:multi. Two or more such subroutines could be defined with the same name, in the same package namespace, provide they were both defined with the C:multi attribute, and their parameter lists were not identical. For example: package LargeNum; package LargeInt;use base 'LargeNum'; package LargeFloat; use base 'LargeNum'; package LargeMath; sub divide(LargeInt $a, LargeInt $b) : multi { ... } sub divide(LargeInt $a, LargeFloat $b) : multi { ... } This creates a (single) multimethod called CLargeMath::divide with two variants. If the multimethod is called with two references to LargeInt objects as arguments: $x = LargeInt-new(1234567890); $y = LargeInt-new(9876543210); $quotient = divide($x, $y); then the first variant is invoked. If the multimethod is called with a LargeInt reference and a LargeFloat reference: $x = LargeInt-new(1234567890); $y = LargeFloat-new(9876543210.12345); $quotient = divide($x, $y); then the second variant is called. Calling the multimethod with any other combination of LargeNum-derived reference arguments (e.g. a reference to a LargeFloat and a reference to a LargeInt, or two LargeFloat references) results in an exception being thrown, with the message: No viable candidate for call to multimethod divide To avoid this, a "catch-all" variant could be specified: sub divide(LargeNum $b, LargeNum $b) : multi { ... } Now, calling Cdivide with (for example) a LargeFloat reference and a LargeInt reference causes this third variant to be invoked. That's because a LargeFloat Iis-a LargeNum (so the first argument is compatible with the first parameter), and a LargeInt Iis-a LargeNum too (so the second argument is compatible with the second parameter). Note that adding this third variant doesn't affect calls to the other two, since multiple dispatch always selects the nearest match. =head2 Finding the "nearest" multimethod The usefulness of multiple dispatch depends on how intelligently the dispatcher decides which variant of a multimethod is "nearest" to a given set of arguments. That decision process is called Idispatch resolution, and it is proposed that it be done (or Iappear to be done, modulo optimization) like this: =over 4 =item 1. If the types of the arguments given (as determined by applying Cref to each in turn) exactly match the set of parameter types specified in any variant of the multimethod, that variant is immediately called. =item 2. Otherwise, the dispatch mechanism compiles a list of viable targets. A viable target is a variant of the multimethod with the same number of parameters as there were arguments passed. In addition, for each parameter the specified parameter type must be a base class of the actual type of the corresponding argument in the actual call (i.e. each argument must belong to a subclass of the corresponding parameter
RFC 200 (v2) Objects: Revamp tie to support extensibility (Massive tie changes)
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Objects: Revamp tie to support extensibility (Massive tie changes) =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 7 Sep 2000 Last Modified: 20 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 200 Version: 2 Status: Developing Requires: RFC 159 =head1 CHANGES 1. Dropped all references to "indirect object" syntax, since it was misleading, inaccurate, and unimplementable. Instead, added a Cuse tie pragma to arbitrarily override functions. 2. Dropped suggestion to merge TIE* methods 3. Added an UNTIE method and dropped the idea that untie should take all references out of scope. =head1 ABSTRACT Ctie is really cool. Mostly. It has an amazing amount of power in concept, but suffers from several limitations which this RFC attempts to address. =head1 DESCRIPTION =head2 Overview Many people have expressed problems with tie, including Larry [1]. Ctie suffers from several limitations: 1. It is non-extensible; you are limited to using functions that have been implemented with tie hooks in them already. 2. Any additional functions require mixed calls to tied and OO interfaces, defeating a chief goal: transparency. 3. It is slow. Very slow, in fact. 4. You can't easily integrate tie and operator overloading. 5. If defining tied and OO interfaces, you must define duplicate functions or use typeglobs. 6. Some parts of the syntax are, well, kludgey This RFC attempts to address all of these points with some changes to syntax and implementation concepts. It interacts with the concept of Bpolymorphic objects, described in BRFC 159, to provide a simple and extensible framework. =head2 New Concepts This RFC proposes two key principles that will provide a more general-purpose Ctie framework: 1. Operator, data, and syntax overloading will be done via the ALLCAPS methods described in BRFC 159. 2. All functions can be overloaded via the Cuse tie pragma. In addition, the declaration of a tie statement is suggested to be changed into a standard indirect object function: $object = tie Tie::Class @array_to_tie; The default Ctieing would be performed by CUNIVERSAL::tie, which would be a new method that properly "blessed" the tied variable and then simply turned around and called the class's CTIE* method, similar to how the builtin Ctie works currently. There are many changes, so let's go through them one at a time and then revisit how they will all tie (ha-ha) together at the end. =head2 Syntax Changes =head3 Drop Ctie builtin and replace with CUNIVERSAL::tie As mentioned above, this allows us to call Ctie in a simple indirect object form. This eliminates one more special-case function which currently requires that quotes be placed around the class name. This syntax should simply be modified to be called on the object it will be tied to, since Ctie is after all an object constructor. =head3 Drop CTIEHANDLE Thanks to the below syntax, differentiating between filehandles and other scalars is no longer important. It would also be very difficult to make this distinction, since in Perl 6 filehandles are intended to be C$scalars. =head3 Continue to do data handling through ALLCAPS methods This will not change. CSTORE and CFETCH, along with other functions described in BRFC 159 and below, will continue to do data handling. In addition, these methods will be used for operator overloading as well, providing a unified Ctie and Cuse overload environment. =head3 Add CUNTIE method called by Cuntie When called, Cuntie currently suffers the somewhat nasty problem of not being able to automatically destroy inner references. This means if you've mixed OO and Ctied calls, you may not be able to destroy your tied object as easily as you like. [2] An CUNTIE method should be added which is called when a tied variable is untied. This solves the problem of CDESTROY not being called when you think it's going to be. =head3 Ability to Ctie arbitrary functions Currently, Ctie suffers from being non-extensible: push @tied_array, $value; sort { $a = $b } @tied_array; The first one can be implemented as CPUSH by your tied array class, but there is no way that you can transparently offer a custom Csort routine. While Perl 5.6 finally has a fairly substantial collection of Ctie methods, it is easy to imagine that future functions will arise which you want to Ctie, but which support has not been added for yet. Plus, if you want to support extra methods of your own, you must mix object and tied calls: # Perl 5 $obj = tie %trans, 'Transaction'; $trans{$var} = $value; $obj-lock($var); Unfortunately, this defeats one of the key purposes of Ctie, which is BOO transparency. And, creating a class that supports both OO and tied interfaces is difficult, requiring typeglobs or duplicate handler
RFC 222 (v2) Interpolation of object method calls
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Interpolation of object method calls =head1 VERSION Maintainer: Michael G Schwern [EMAIL PROTECTED] Date: 14 Sep 2000 Last Modified: 17 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 222 Version: 2 Status: Developing =head1 CHANGES =head2 v2. Mistakenly said that C"$obj-meth("Foo")" should interpolate. It should, of course, be C"$obj-meth(\"Foo\")". Added a section about variable method calls C"$obj-$meth()". MIGRATION updated accordingly. Clarified the title, restricting this RFC to object methods only. Class methods will be delt with in a seperate RFC. The caveat about whitespace now has its own section. =head1 ABSTRACT Method calls should interpolate in double-quoted strings, and similar locations. print "Today's weather will be $weather-temp degrees and sunny."; Would deparse to: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; =head1 DESCRIPTION =head2 The Current Problem With OO Interpolation Object-oriented programming encourages data-hiding, and one of the most basic tool for this is the accessor method. For reasons which should be obvious, C$obj-foo() is usually better than C$obj-{foo}. However, there are several barriers to using an accessor method as simply as one does a hash lookup. Other RFCs deal with most of the current issues, but a basic one still remains. print "Today's weather will be $weather-temp degrees and sunny."; This does not DWIM. Instead of interpolating C$weather-temp as a method call, it comes out as C$weather.'-temp' and is usually followed immediately by the question "What does 'Weather=HASH(0x80d4174)-temp' mean??" Most programmers learning OO Perl expect this to work and are surprised to find that it does not. Work arounds abound: # If I wanted printf(), I'd have written it in C. printf "Today's weather will be %d degrees and sunny.", $weather-temp; my $temp = $weather-temp; print "Today's weather will be $temp degrees and sunny."; print "Today's weather will be @{[$weather-temp]} degrees and sunny."; print "Today's weather will be ".$weather-temp." degrees and sunny."; None are as simple and as obvious as: print "Today's weather will be $weather-{temp} degrees and sunny."; and because of this users groan at having to use accessor methods and are often tempted to violate encapsulation for ease of use. =head2 Proposed Solution - Interpolate Methods Therefore, it is proposed that direct object method calls be interpolated inside double quoted strings and similar constructs. print "Today's weather will be $weather-temp degrees and sunny."; should parse out as: print 'Today\'s weather will be '.$weather-temp().' degrees and sunny.'; thus returning DWIMness to methods and strings and removing one barrier to accessor method's acceptance over hash lookups for objects. Methods will be run in scalar context. A method which returns a single scalar is treated normally. If a list is returned, it should be treated same as array interpolation. The list seperator will be applied. In effect, the deparsing will really work out as follows: print 'Today\'s weather will be '.join($", $weather-temp()). ' degrees and sunny.'; However if temp() calls wantarray(), the result will be FALSE (scalar). (For the remainder of the RFC, the join() will be assumed when discussing deparsing for brevity.) Should it be decided that a formal distinction be made between accessor methods and other types (RFC 95), method interpolation should interpolate Bany method. =head2 Argument passing Interpolation should also handle passing arguments to methods in a string: print "Today's weather will be $weather-temp(\"F\") degrees and sunny."; BNOTE escaping the quotes is analagous to how C"$hash{\"foo\"}" currently interpolates. This should deparse to: print 'Today\'s weather will be '.$weather-temp("F"). ' degrees and sunny.'; The arguments to the method are considered as normal expressions, thus: print "There is $obj-foo(this = $yar, that = 2 + 2) in my head."; deparses as: print 'There is '.$obj-foo(this = $yar, that = 2 + 2). ' in my head."; =head2 Variable method calls The accessor method is not always known when the program is written, thus variable method calls should also be interpolated: my $what = 'temperature'; print "The $what will be $weather-$what() with a 50% chance of kittens."; interpolates to my $what = 'temperature'; print 'The '.$what.' will be '.$weather-$what().' with a 50% chance of kittens.'; As with normal usage, the parenthesis are mandatory. This: my $what = 'color'; print "I like traffic lights, but only when they're $light-$what"; interpolates to: my $what = 'color'; print 'I like traffic lights, but only when they're '.$light.'-'.$what; =head2 Whitespace
RFC 73 (v2) All Perl core functions should return objects
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE All Perl core functions should return objects =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 8 Aug 2000 Last-Modified: 15 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 73 Version: 2 Status: Frozen Requires: RFC 159 =head1 ABSTRACT In the past, Perl has only provided two return options for its builtin functions: scalars or lists. In a scalar context, only one select value was returned, greatly impacting the functionality of the function (unless you like pulling apart long lists, or pain, or both). The reason this was done was to allow easy access to string/numeric data, and because polymorphic objects were not a reality. However, objects can use the mechanisms described in BRFC 159: True Polymorphic Objects to become strings, numbers, and other data types on-demand in Perl 6. As such, we should make all Perl functions return objects in a scalar context in Perl 6. =head1 NOTES ON FREEZE This is mainly a philosophical document designed to show how the methods described in BRFC 159: True Polymorphic Objects can be used to give us a greater amount of core power in Perl 6. One actual proposed implementation of these ideas can be found in BRFC 48, which suggests a new Cdate function which produces a polymorphic object in scalar context. The only fear was performance-related; however, as Dan Sugalski himself pointed out, the -internals group will probably wind up putting vtable stuff in core. In this case, performance should not be a concern because OO will be tightly integrated from ground up. =head1 DESCRIPTION When several of the mechanisms proposed in other RFC's combine, especially BRFC 159, we have the power in Perl 6 to pass many more things around as objects, converting them to strings/numbers/etc as they're needed. This gives us much power, since we present both objects and "true" scalars to beginners and advanced Perl users alike with one common set of functions. As such, objects are embedded in Perl from the ground up. Others have proposed typing objects, and extracting them that way: my $uid = getpwnam $user;# "true" scalar uid my pw $pw = getpwnam $user;# object of type "pw" However, this has a couple problems: 1. You have to have the correct object class and, at the very least, alter your script's syntax. 2. You can't make $pw look like $uid transparently. Instead, having objects that walk and talk like scalars on demand is a more powerful approach. Note that this RFC does not necessarily preclude being able to type objects and pull out specific classes. The two approaches could be combined, giving multi-class objects that can be transparently accessed as "true" scalars. We'll start out with complex examples, where it's obvious how this is a benefit, and go down to simpler functions, where it might be less obvious. =head2 Complex Functions Let's choose Cstat, since it's an easy target. Currently, it only returns one of two things: 1. A massive 13-element list (LIST context) 2. A boolean success/failure (SCALAR context) Neither of these is particularly useful, unless you like pain. To get a decent interface, you have to use CFile::stat or some other module. Instead, let's put an object-oriented interface in the core: $stat = stat $file;# returns an object @stat = stat $file;# legacy list (like current) %stat = stat $file;# hash (see RFC 21) print "$stat"; # calls $stat-STRING, which # could print the filename or # some other useful piece of info Note that our legacy calling methods are unaffected, but we now have an object too. The boolean truth value is simplistic to determine still, you simply have to say: $stat = stat $file or die "Can't stat $file: $!"; The object methods of the C$stat object are powerful enough that special cases like C_ no longer have to exist. You can stat multiple files out of order and still get the benefits of cached Cstat calls by using the object interface: $f1 = stat $file1 or die; $f2 = stat $file2 or die; if ( $f1-size 0 and $f2-owner == 0 ) { print "root-owned $file1 is mode ", $f1-mode 0; if ( $f1-mtime time ) { # here, "$f1" is $f1-STRING == $f1-filename warn "Warning: bad mojo, $f1 has an mtime in the future!\n"; } } Now, we have a full object-oriented Cstat implementation, wrapped in a tidy function that can work just like Perl 5's if you want it to. As a second example, let's examine Cgetpwnam, whose return options are: 1. A pretty dang big 9-element list 2. The numeric user id Cgetpwnam differs from Cstat in that you have to actually use what you get in a CSCALAR context in many situations. However, this can be easily addressed thanks to BRFC 159: $pw = getpwnam $username; # get
RFC 159 (v2) True Polymorphic Objects
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE True Polymorphic Objects =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 25 Aug 2000 Last-Modified: 16 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 159 Version: 2 Status: Frozen =head1 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 Ctie to help fix this issue, but Ctie is limited and slow. You can also Cuse 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 Btrue 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). =head1 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. =head1 DESCRIPTION =head1 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, C$y and C$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, C$y and C$name are objects, but we don't have to care. These objects have a key property: Icontext sensitivity. They have numerous different methods which are each called only in specific instances. So, being called in a numeric context calls CNUMBER, whereas being called in a string context would call CSTRING. Plus, operators are overloadable as well. This means that we might decide to overload C+ 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. =head2 Polymorphic Methods The following are the proposed methods for Perl 6 objects. Note that these methods are completely Ioptional 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 CSTRING, CNUMBER, and CBOOLEAN are specialized forms of CFETCH. If you define them, they are used instead of CFETCH in the given context, otherwise CFETCH is used. Also note that the operators, when overloaded, behave similarly to 'use overload', but on an Iobject 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 NUMEQCalled in == context NUMNECalled in != context NUMLTCalled in context NUMGTCalled in context NUMLECalled in = context NUMGECalled in = context STRCMP Called in cmp context STREQCalled in eq context STRNECalled in ne context STRLTCalled in lt context STRGTCalled in gt context STRLECalled in le context STRGECalled in ge context BITAND Called in context BITORCalled in | context BITXOR Called in ^ context BITNOT Called in ~ context LOGNOT Called in ! context LOGHIGHAND Called in context LOGHIGHORCalled in || context LOGLOWANDCalled in and context LOGLOWOR Called in or context LOGIFELSECalled in ?: context
RFC 101 (v3) Apache-like Event and Dispatch Handlers
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Apache-like Event and Dispatch Handlers =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 14 Aug 2000 Last Modified: 25 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 101 Version: 3 Status: Frozen =head1 ABSTRACT A complete Perl 5 implementation of this can be found as Class::Handler http://www.perl.com/CPAN/authors/id/N/NW/NWIGER/Class-Handler-1.03.tar.gz Currently, there is no way to have multiple methods or modules for dealing with events without significant contortions: $data = $r1-get_data || $r2-stuff || $r3-func; $r1-do_stuff(@vals) or $r1-do_this(@vals); These simple cases can actually be tolerated. However, there are many more complex cases which cannot be handled at all in Perl. These include opening files only in certain directories, having methods decline or partially handle requests, and so on. This RFC proposes the idea of a Chandler, which is a special type of class that is actually composed of one or more classes. Their operation is very similar to Apache handlers: requests can be handled, declined, or partially handled, without the top-level program having to know about it. =head1 NOTES ON FREEZE The only concern ever raised was on why this should be core-worthy. One word: speed. Currently, it can be implemented via CAUTOLOAD, but this is slow. Also, other RFCs such as BRFC 14 rely on the notion of handlers to gain important functionality (such as the ability to transparently open URLs and different file types). Damian has a separate RFC on pre and post sub handlers. It may be possible to integrate the two into a common handler framework/methodology. Unfortunately, I don't think either of us has the time to do this at this point because of the upcoming RFC deadline. However, this is something that should definitely be looked into in the future. =head1 DESCRIPTION =head2 Overview The concept of a Chandler is actually not that complex. In the simplest case, it can be thought of as a type of abstraction: sub open_it { my $file = shift; return open $file || HTTP::open $file || FTP::open $file; } Then, in your script, you would simply say: $fileobject = open_it " $filename"; This gives you several benefits: 1. The internal handling of open_it can be changed without having to update all your programs 2. Each operation can actually partially process the request, if appropriate 2. Your program is easier to read and understand From a Perl standpoint, these handlers work just like normal functions and classes: they have methods, properties, inheritance, and so forth. The only difference is that these handlers do not live in an external file, but rather are assembled internally by Perl. =head2 Adding and Using Handlers First, the examples assume that the reader is somewhat familiar with RFC 14. If not, it is recommended that you give it a quick read at http://dev.perl.org/rfc/14.pod There are several competing syntaxes that I have for this proposal. I've provided the one that I think is the best, but this is open to discussion. The proposed syntax is to use a pragmatic style: use handler 'http' = 'MyHTTP'; use handler 'http' = 'LWP::UserAgent'; This would assemble a Chandler called 'http' which could then be used in functions in your program. This handler would be a pseudo-class that inherits methods from CMyHTTP and CLWP::UserAgent, in that order. So: $fo = open http "http://www.yahoo.com" or die; would call Chttp-open, consistent with the current Perl implementation. The only difference would be that Chttp now tries to call the Copen() method from CMyHTTP and CLWP::UserAgent. As such, the above call would result in the following flow chart: $fo http-openundef ^ | ^ | | | | Does MyHTTP::open exist?| |YES/ \NO | | / \ | | Try it Does LWP::UserAgent::open exist? | | / \^ YES/ \NO | |OK/ \UNDEF / / --- -- Try it| | / \ | | OK/\UNDEF | - - Some highlights: 1. Each class's open() method is tried in turn. 2. If undef is returned, the next one in sequence is tried. 3. If 'OK' (simply meaning 1 or some other true value, like $fo) is returned, that is propagated out and returned by the top-level handler. 4. All classes are tried until 'OK' is returned or the last one is reached. This allows you to easily chain classes
RFC 152 (v2) Replace invocant in @_ with self() builtin
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Replace invocant in @_ with self() builtin =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 24 Aug 2000 Last Modified: 24 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 152 Version: 2 Status: Frozen =head1 ABSTRACT Currently, the invocant is passed into a sub as the first element of @_, leading to the familiar construct: my $self = shift; However, this is a big PITA. In particular, if you support several different calling forms (like CGI.pm), you have to check whether $_[0] is a ref or class name, etc. This RFC, therefore, proposes a new builtin called Cself() which will return the correct invocant information. This has the added advantage that it is consistent with Ccaller(), Cwant(), ref(), and other context functions. =head1 DESCRIPTION =head2 Syntax The new function Cself() would be called in the following way: sub fullname { my $self = self; @_ ? $self-{STATE}-{fullname} = $_[0] : $self-{STATE}-{fullname}; } sub my_junk { my $this = self; $this-fork_o_matic(@_); } # Or even... sub error { carp @_ if self-config('VerboseErrors'); } sub uid { @_ ? self-{uid} = $_[0] : self-{uid}; } The return value of Cself() would be similar to the current invocant in $_[0], with increased flexibility. In particular, it can be called anywhere and everywhere, not just within a method. Depending on the context it's called in, the return value of Cself() will be: 1. A reference to the object, within an object method 2. The name of the package, within a package 3. Undef, if a sub is not called as a method These different return values give us the ability to call Cself() anywhere within Perl 6 code: package MyPackage; # ... many other functions ... sub do_stuff { print "Hello, @_" if self-config('Yep'); } self-do_stuff; # MyPackage-do_stuff package main; my $mp = new MyPackage; $mp-config('Yep') = 1; $mp-do_stuff('Nate');# prints "Hello, Nate" In addition, having a routine called Cself() has the major advantage that it hides the internal magic and scoping from the user. Just like using Cwant() instead of a special variable called C$WANT, Cself() makes using and comprehending contexts easy, simply changing the Perl 5 rule: "The invocant is passed into subs as $_[0] in OO contexts" To the simpler still: "The invocant is always gotten by calling self()" This provides a consistent interface, since Cself() can be called anywhere, just like Ccaller(), Cwant(), and other context functions. =head2 Arguments against Cuse invocant This RFC was released prior to, and remains in opposition to, RFC 233, which proposes a Cuse invocant pragma that provides the flexibility to name the invocant anything you want. As many have noted, Perl is already hard enough. Cuse invocant only gives us multiple ways to do something without adding value, only confusion, by promoting an inconsistent interface. Like providing a means to rename C@ARGV and CSTDIN because a person prefers C@args and Coutput, Cuse invocant further complicates an issue which should only be made easier. The author of this RFC Bloves Perl and loves its flexibility. However, just like choosing a name for Ccaller, Cwant, Cprint, C@ARGV, and so forth, we need to choose a name for Cself as well to ease the burden on the programmer. "Choosing an interface" does not amount to "being un-Perlish" as some might purport to suggest. In fact, just the opposite: We're decreasing the amount of time a user has to spend decoding somebody else's invocant naming scheme by providing a very Perlishly-named function. BThis makes things easier. If it is vital that the invocant must be named something specific, then a person can always use a sub wrapper, tie, or a typeglob to rename it appropriately. Actually, they don't even have to go to these extremes since they can still do this: sub getdata { my $this = self; return $this-{DATA}-{$_[0]}; } (that is, assign to a custom variable) anywhere they want to. Finally, the author would be more than happy to settle for the selection of something different than Cself, such as Cthis(), C$SELF, or even C$ME. The main point is that we need to choose something, because doing so makes the language more consistent and easier (combatting two widespread criticisms of Perl). =head1 IMPLEMENTATION Replace the invocant usually included in $_[0] with Cself(). Stop passing the invocant in @_. =head1 MIGRATION Backwards compatibility is simple. Subs can simply have the expression: unshift @_, self if self; Added as the first line of the sub, since Cself() will return undef if not in an OO context. =head1 REFERENCES Critique of the Cuse invocant pragma: http://www.mail-archive.com/perl6-language@perl.org/msg03952.html Outline of the
RFC 279 (v1) my() syntax extensions and attribute declarations
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE my() syntax extensions and attribute declarations =head1 VERSION Maintainer: Nathan Wiger [EMAIL PROTECTED] Date: 24 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 279 Version: 1 Status: Developing =head1 ABSTRACT This RFC fleshes out variable declarations with Cmy, and also proposes a way to assign attributes without the need for a Cmy anywhere. =head1 DESCRIPTION Camel-3 shows some interesting hints of what's been proposed for Cmy declarations: my type $var :attribute = $value; And we all know that you can use Cmy to declare a group of variables: my($x, $y, $z); Here's the issues: 1. How do the two jive together? 2. Should it be possible to assign attributes to individiual elements of hashes/arrays? (yes) =head2 Cohesive Cmy syntax This RFC proposes that you be able to group multiple variables of the same type within parens: my int ($x, $y, $z); my int ($x :64bit, $y :32bit, $z); It seems most logical that: 1. The type will be the same across variables; this is common usage in other languages because it makes sense. 2. The attributes will be different for different variables. As such, multiple attributes can be assigned and grouped flexibly: my int ($x, $y, $z) :64bit; # all are 64-bit my int ($x, $y, $z :unsigned) :64bit; # plus $z is unsigned Note that multiple types cannot be specified on the same line. To declare variables of multiple types, you must use separate statements: my int ($x, $y, $z) :64bit; my string ($firstname, $lastname :long); This is consistent with other languages and also makes parsing realistic. =head2 Assigning attributes to individual elements of hashes/arrays This is potentially very useful. ":laccess", ":raccess", ":public", ":private", and others spring to mind as potential candidates for this. This RFC proposes that in addition to attributes being assignable to a whole entity: my int @a :64bit; # makes each element a 64-bit int my string %h :long; # each key/val is long string They can also be declared on individual elements, without the need for Cmy: $a[0] :32bit = get_val; # 32-bit $r-{name} :private = "Nate"; # privatize single value $s-{VAL} :laccess('data') = ""; # lvalue autoaccessor However, a problem arises in how to assign types to singular elements, since this requires a Cmy: my int $a[0] :64bit; # just makes that single element # a lexically-scoped 64-bit int? my string $h{name} = ""; # cast $h{name} to string, rescope %h? Currently, lexical scope has no meaning for individual elements of hashes and arrays. However, assigning attributes and even types to individual elements seems useful. There's two ways around this that I see: 1. On my'ing of an individual hash/array element, the entire hash/array is rescoped to the nearest block. 2. Only the individual element is rescoped, similar to what happens when you do this: my $x = 5; { my $x = 10; } Either of these solutions is acceptable, and they both have their pluses and minuses. The second one seems more consistent, but is potentially extremely difficult to implement. =head1 IMPLEMENTATION Hold on. =head1 MIGRATION None. This introduces a more flexible syntax but does not break old ones. =head1 REFERENCES Camel for the Cmy syntax.