Sub::Nary - Try to count how many elements a subroutine can return in list context.
Version 0.03
use Sub::Nary; my $sn = Sub::Nary->new(); my $r = $sn->nary(\&hlagh);
This module uses the B framework to walk into subroutines and try to guess how many scalars are likely to be returned in list context. It's not always possible to give a definitive answer to this question at compile time, so the results are given in terms of "probability of return" (to be understood in a sense described below).
new
The usual constructor. Currently takes no argument.
nary $coderef
Takes a code reference to a named or anonymous subroutine, and returns a hash reference whose keys are the possible numbers of returning scalars, and the corresponding values the "probability" to get them. The special key 'list' is used to denote a possibly infinite number of returned arguments. The return value hence would look at
'list'
{ 1 => 0.2, 2 => 0.4, 4 => 0.3, list => 0.1 }
that is, we should get 1 scalar 1 time over 5 and so on. The sum of all values is 1. The returned result, and all the results obtained from intermediate subs, are cached into the object.
1
5
flush
Flushes the Sub::Nary object cache. Returns the object itself.
The probability is computed as such :
When branching, each branch is considered equally possible.
For example, the subroutine
sub simple { if (rand < 0.1) { return 1; } else { return 2, 3; } }
is seen returning one or two arguments each with probability 1/2. As for
1/2
sub hlagh { my $x = rand; if ($x < 0.1) { return 1, 2, 3; } elsif ($x > 0.9) { return 4, 5; } }
it is considered to return 3 scalars with probability 1/2, 2 with probability 1/2 * 1/2 = 1/4 and 1 (when the two tests fail, the last computed value is returned, which here is $x > 0.9 evaluated in the scalar context of the test) with remaining probability 1/4.
3
2
1/2 * 1/2 = 1/4
$x > 0.9
1/4
The total probability law for a given returning point is the convolution product of the probabilities of its list elements.
As such,
sub notsosimple { return 1, simple(), 2 }
returns 3 or 4 arguments with probability 1/2 ; and
4
sub double { return simple(), simple() }
never returns 1 argument but returns 2 with probability 1/2 * 1/2 = 1/4, 3 with probability 1/2 * 1/2 + 1/2 * 1/2 = 1/2 and 4 with probability 1/4 too.
1/2 * 1/2 + 1/2 * 1/2 = 1/2
If a core function may return different numbers of scalars, each kind is considered equally possible.
For example, stat returns 13 elements on success and 0 on error. The according probability will then be { 0 => 0.5, 13 => 0.5 }.
stat
13
0
{ 0 => 0.5, 13 => 0.5 }
The list state is absorbing in regard of all the other ones.
list
This is just a pedantic way to say that "list + fixed length = list". That's why
sub listy { return 1, simple(), @_ }
is considered as always returning an unbounded list.
Also, the convolution law does not behave the same when list elements are involved : in the following example,
sub oneorlist { if (rand < 0.1) { return 1 } else { return @_ } } sub composed { return oneorlist(), oneorlist() }
composed returns 2 scalars with probability 1/2 * 1/2 = 1/4 and a list with probability 3/4.
composed
3/4
An object-oriented module shouldn't export any function, and so does this one.
The algorithm may be pessimistic (things seen as list while they are of fixed length) but not optimistic (the opposite, duh).
wantarray isn't specialized when encountered in the optree.
wantarray
perl 5.8.1.
Carp (standard since perl 5), B (since perl 5.005) and XSLoader (since perl 5.006).
Vincent Pit, <perl at profvince.com>, http://www.profvince.com.
<perl at profvince.com>
You can contact me by mail or on #perl @ FreeNode (vincent or Prof_Vince).
Please report any bugs or feature requests to bug-b-nary at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Sub-Nary. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
bug-b-nary at rt.cpan.org
You can find documentation for this module with the perldoc command.
perldoc Sub::Nary
Tests code coverage report is available at http://www.profvince.com/perl/cover/Sub-Nary.
Thanks to Sebastien Aperghis-Tramoni for helping to name this module.
Copyright 2008 Vincent Pit, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Sub::Nary, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Sub::Nary
CPAN shell
perl -MCPAN -e shell install Sub::Nary
For more information on module installation, please visit the detailed CPAN module installation guide.