Author: larry Date: Thu May 25 11:21:16 2006 New Revision: 9307 Modified: doc/trunk/design/syn/S06.pod
Log: Clarifying the distinction between the "of" and "where" return types. Modified: doc/trunk/design/syn/S06.pod ============================================================================== --- doc/trunk/design/syn/S06.pod (original) +++ doc/trunk/design/syn/S06.pod Thu May 25 11:21:16 2006 @@ -13,9 +13,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 21 Mar 2003 - Last Modified: 14 May 2006 + Last Modified: 24 May 2006 Number: 6 - Version: 35 + Version: 36 This document summarizes Apocalypse 6, which covers subroutines and the @@ -288,7 +288,7 @@ including Unicode characters. For example: sub infix:<(c)> ($text, $owner) { return $text but Copyright($owner) } - method prefix:<±> (Num $x) returns Num { return +$x | -$x } + method prefix:<±> (Num $x --> Num) { return +$x | -$x } multi sub postfix:<!> (Int $n) { $n < 2 ?? 1 !! $n*($n-1)! } macro circumfix:«<!-- -->» ($text) is parsed / .*? / { "" } @@ -1238,7 +1238,7 @@ Note that unlike a sub declaration, a regex-embedded signature has no associated "returns" syntactic slot, so you have to use C<< --> >> -within the signature to specify the type of the signature, or match as +within the signature to specify the C<of> type of the signature, or match as an arglist: :(Num, Num --> Coord) @@ -1395,15 +1395,21 @@ Explicit types are optional. Perl variables have two associated types: their "value type" and their "implementation type". (More generally, any container has an implementation type, including subroutines and modules.) +The value type is stored as its C<of> property, while the implementation +type of the container is just the object type of the container itself. The value type specifies what kinds of values may be stored in the -variable. A value type is given as a prefix or with the C<returns> or -C<of> keywords: +variable. A value type is given as a prefix or with the C<of> keyword: my Dog $spot; - my $spot returns Dog; my $spot of Dog; +In either case this sets the C<of> property of the container to C<Dog>. +Subroutines have a variant of the C<of> property, C<returns>, that +sets the C<returns> property instead. The C<returns> property specifies +a constraint to be checked upon calling C<return> that, unlike the C<of> +property, is not advertized as the type of the routine: + our Animal sub get_pet() {...} sub get_pet() returns Animal {...} sub get_pet() of Animal {...} @@ -1431,6 +1437,13 @@ run-time C<tie> statement unless the variable is explicitly declared with an implementation type that does the C<Tieable> role. +However, package variables are always considered C<Tieable> by default. +As a consequence, all named packages are also C<Tieable> by default. +Classes and modules may be viewed as differently tied packages. +Looking at it from the other direction, classes and modules that +wish to be bound to a global package name must be able to do the +C<Package> role. + =head2 Hierarchical types A non-scalar type may be qualified, in order to specify what type of @@ -1449,19 +1462,16 @@ actually means: - my Hash[returns => Array[returns => Recipe]] %book; + my Hash[of => Array[of => Recipe]] %book; Because the actual variable can be hard to find when complex types are specified, there is a postfix form as well: my Hash of Array of Recipe %book; # HoHoAoRecipe my %book of Hash of Array of Recipe; # same thing - my %book returns Hash of Array of Recipe; # same thing -The C<returns> form is more commonly seen in subroutines: +The C<returns> form may be used in subroutines: - my Hash of Array of Recipe sub get_book ($key) {...} - my sub get_book ($key) of Hash of Array of Recipe {...} my sub get_book ($key) returns Hash of Array of Recipe {...} Alternately, the return type may be specified within the signature: @@ -1469,8 +1479,14 @@ my sub get_book ($key --> Hash of Array of Recipe) {...} There is a slight difference, insofar as the type inferencer will -ignore a C<returns> but pay attention to C<< --> >> or prefix type declarations. -Only the inside of the subroutine pays attention to C<returns>. +ignore a C<returns> but pay attention to C<< --> >> or prefix type +declarations, also known as the C<of> type. Only the inside of the +subroutine pays attention to C<returns>. + +You may also specify the C<of> type as the C<of> trait: + + my Hash of Array of Recipe sub get_book ($key) {...} + my sub get_book ($key) of Hash of Array of Recipe {...} =head2 Polymorphic types @@ -1524,42 +1540,53 @@ =head2 Return types On a scoped subroutine, a return type can be specified before or -after the name: - - our Egg sub lay {...} - our sub lay returns Egg {...} - - my Rabbit sub hat {...} - my sub hat returns Rabbit {...} +after the name. We call all return types "return types", but distinguish +two kinds of return type, the C<where> type from the C<of> type, because +the C<of> type must be an "official" named type, while the C<where> type +is merely applied as a constraint to what may be returned by the routine. + + our Egg sub lay {...} # of type + our sub lay returns Egg {...} # where type + our sub lay of Egg {...} # of type + our sub lay (--> Egg) {...} # of type + + my Rabbit sub hat {...} # of type + my sub hat returns Rabbit {...} # where type + my sub hat of Rabbit {...} # of type + my sub hat (--> Rabbit) {...} # of type If a subroutine is not explicitly scoped, it belongs to the current namespace (module, class, grammar, or package), as if it's scoped with the C<our> scope modifier. Any return type must go after the name: - sub lay returns Egg {...} + sub lay returns Egg {...} # where type + sub lay of Egg {...} # of type + sub lay (--> Egg) {...} # of type On an anonymous subroutine, any return type can only go after the C<sub> keyword: - $lay = sub returns Egg {...}; + $lay = sub returns Egg {...}; # where type + $lay = sub of Egg {...}; # of type + $lay = sub (--> Egg) {...}; # of type -but you can use a scope modifier to introduce a return type: +but you can use a scope modifier to introduce an C<of> prefix type: - $lay = my Egg sub {...}; - $hat = my Rabbit sub {...}; + $lay = my Egg sub {...}; # of type + $hat = my Rabbit sub {...}; # of type Because they are anonymous, you can change the C<my> modifier to C<our> without affecting the meaning. -The return type may also be specified after a C<< --> >> token within the -signature. This doesn't mean exactly the same thing as C<returns>. The -arrow form is an "official" return type, and may be used to do type -inferencing outside the sub. The C<returns> form only makes the return -type available to the internals of the sub so that the C<return> statement -can know its context, but outside the sub we don't know anything -about the return value, as if no return type had been declared. The prefix -form actually corresponds to the C<< --> >> semantics rather than the -C<returns> semantics, so the return type of +The return type may also be specified after a C<< --> >> token within +the signature. This doesn't mean exactly the same thing as C<returns>. +The C<of> type is the "official" return type, and may therefore be +used to do type inferencing outside the sub. The C<where> type only +makes the return type available to the internals of the sub so that +the C<return> statement can know its context, but outside the sub we +don't know anything about the return value, as if no return type had +been declared. The prefix form specifies the C<of> type rather than +the C<where> type, so the return type of my Fish sub wanda ($x) { ... } @@ -1571,7 +1598,7 @@ my sub wanda ($x) returns Fish { ... } -It is possible for the outer type to disagree with the inner type: +It is possible for the C<of> type to disagree with the C<where> type: my Squid sub wanda ($x) returns Fish { ... } @@ -1623,7 +1650,11 @@ =item C<returns>/C<is returns> -The type returned by a subroutine. +The C<where> type constraint that a routine imposes in its return value. + +=item C<of>/C<is of> + +The C<of> type that is the official return type of the routine. =item C<will do>