Vincent Pit

# NAME

Sub::Nary - Try to count how many elements a subroutine can return in list context.

Version 0.03

# SYNOPSIS

``````    use Sub::Nary;

my \$sn = Sub::Nary->new();
my \$r  = \$sn->nary(\&hlagh);``````

# DESCRIPTION

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).

# METHODS

## `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

``    { 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.

## `flush`

Flushes the Sub::Nary object cache. Returns the object itself.

# PROBABILITY OF RETURN

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

``````    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`.

• 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

``````    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.

• 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 }`.

• The `list` state is absorbing in regard of all the other ones.

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`.

# EXPORT

An object-oriented module shouldn't export any function, and so does this one.

# CAVEATS

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.

# DEPENDENCIES

perl 5.8.1.

Carp (standard since perl 5), B (since perl 5.005) and XSLoader (since perl 5.006).

# AUTHOR

Vincent Pit, `<perl at profvince.com>`, http://www.profvince.com.

You can contact me by mail or on #perl @ FreeNode (vincent or Prof_Vince).

# BUGS

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.

# SUPPORT

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.

# ACKNOWLEDGEMENTS

Thanks to Sebastien Aperghis-Tramoni for helping to name this module.