=head1 TITLE
Replace C<wantarray> with a generic C<want> function
=head1 VERSION
Maintainer: Damian Conway <[EMAIL PROTECTED]>
Date: 4 August 2000
Version: 1.00
Mailing List: [EMAIL PROTECTED]
Number: 21
=head1 ABSTRACT
This RFC proposes to extend the number of detectable calling contexts
and replace the limited (and misnamed) context detection of C<wantarray>
with a more precise and general mechanism.
=head1 DESCRIPTION
C<want I<LIST>>
C<want> takes a list of strings that describe aspects of the context in
which the current subroutine has been called. It returns a list
indicating whether or not the current subroutine's call context matches
all the aspects specified in the list. If some aspect of the context
does not match the argument list, the entire C<want> fails and
an empty list is returned. Otherwise, a list of at least one integer
element is returned.
That integer (the "expectation count") indicates the number of return
values expected by the context. For void contexts, the expectation count
is always zero; for scalar contexts, it is always zero or one; for array
contexts it may be any non-negative number.
If the context is expecting an unspecified number of return values
(typically because the result is being assigned to an array variable),
the expectation count is the largest representable integer (C<~0>).
If C<want> is called in a scalar hashref context without arguments, it returns a
reference to a hash whose keys are all aspects that are currently true.
If C<want> is called in any other context without arguments, it returns a
list consisting of the expectation count, followed by all aspects that
are currently true.
The various aspects that may be specified are:
=over 8
=item 'LVALUE'
The subroutine call is being used as an lvalue:
func() = 0;
=item 'RVALUE'
The subroutine call is being used as an rvalue:
$val = func();
@vals = func();
=item 'LIST'
The subroutine was called in a list context:
@vals = func();
print func();
=item 'SCALAR'
The subroutine was called in a scalar context:
$val = func();
=item 'VOID'
The subroutine was called in a void context:
func();
=item 'HASH'
The subroutine was called in a context where its return value is
assigned to (or treated as???) a hash:
%hash = func();
@keys = keys func(); # ???
=item 'STRING'
The subroutine was called in a stringifying context:
$val = $hash{func()};
print func();
=item 'NUMBER'
The subroutine was called in a numerifying context:
$val = func() * 2;
$val = sin(func());
=item 'INTEGER'
The subroutine was called in a numerifying context that
requires an integer:
$val = $array[func()];
$val = "str" x func();
=item 'BOOLEAN'
The subroutine was called in a boolean context:
if ( func() ) {}
$val = func() || 0;
$val = func() or die;
=item 'SCALARREF'
The subroutine was called in a context that expects a scalar reference:
$val = ${func()};
=item 'ARRAYREF'
The subroutine was called in a context that requires an array reference be returned:
func()->[$index];
push @{func()}, $val;
=item 'HASHREF'
The subroutine was called in a context that requires a hash reference be returned:
func()->{key};
@keys = keys %{func()};
=item 'OBJREF'
The subroutine was called in a context that requires an object reference be returned:
func()->method();
=item 'CODEREF'
The subroutine was called in a context that requires a code reference be returned:
func()->();
&{func()}();
=item 'IOREF'
The subroutine was called in a context that requires a filehandle reference be
returned:
print {func()} @data;
=item I<Classname>
The subroutine was called in a context that would like to see an object of the named
class returned:
my Dog $spot = func(); # want 'Dog' returns true
=back
=head2 Example
our ($data, @data) ;
sub lastdata : lvalue {
if ($DEBUG)
{
my ($expcnt,@aspects) = want;
print "lastdata called in @aspects context\n";
print "expected $expcnt return values\n";
}
return if want->{VOID};
return $data if want qw(LVALUE SCALAR);
return "$data" if want 'SCALAR', 'STRING
return eval{$data+0}||0 if want 'SCALAR', 'NUMBER';
return $data if want 'SCALAR', 'BOOLEAN';
if (my ($count) = want 'LIST')
{
return @data if $count > @data;
return @data[0..$count-1];
}
}
=head2 Listing of possible context combinations:
within &func, &want returns: when:
============================ =====
(0, VOID, RVALUE) ;func();
(1, SCALAR, LVALUE) func() = $x;
(0, SCALAR, RVALUE) ; scalar func();
(1, SCALAR, RVALUE) $x = func();
(1, SCALAR, RVALUE, STRING ) $x .= func();
(1, SCALAR, RVALUE, BOOLEAN) die if func();
(1, SCALAR, RVALUE, NUMBER ) $x + func();
(1, SCALAR, RVALUE, NUMBER, INTEGER) ~func(); $array[func()];
(1, SCALAR, RVALUE, SCALARREF) ${func()};
(1, SCALAR, RVALUE, ARRAYREF) func()->[$index];
(1, SCALAR, RVALUE, HASHREF) func()->{key};
(1, SCALAR, RVALUE, CODEREF) func()->(@args);
(1, SCALAR, RVALUE, OBJREF) func()->method();
(1, SCALAR, RVALUE, IOREF) print {func()} @data;
(1, SCALAR, RVALUE, Dog) my Dog $spot = func();
(0, LIST, RVALUE) () = func();
(1, LIST, RVALUE) ($x) = func();
(~0, LIST, RVALUE) ($x, @array) = func();
(~0, LIST, RVALUE) @array = func();
(~0, LIST, RVALUE) print func();
(~0, LIST, RVALUE, HASH) %hash = func();
=head1 IMPLEMENTATION
Dammit, Jim, I'm a doctor, not an engineer!
=head1 REFERENCES
See also: perlfunc (C<wantarray>)