NAME

Perl6::Subs - Define your subroutines in the Perl 6 style

VERSION

Version 0.03

SYNOPSIS

use Perl6::Subs;

sub get (Array $x) { pop @$x }

method foo { $self->bar }        # default invocant: '$self'

DESCRIPTION

Perl6::Subs lets you write subroutine definitions in Perl6 syntax, with some limitations. Given a subroutine defined with a Perl 6 prototype, Perl6::Subs generates Perl 5 code for that subroutine that will, at runtime: declare the formal parameters, assign them their values, and validate their contents.

Perl6::Subs supports parameters of five categories:

  • invocant (e.g. $self) -- marked by a trailing colon rather than the usual comma

  • mandatory positional -- without decoration

  • optional positional -- with a "?" before the variable name

  • optional named -- with a "+" before the variable name

  • required named -- with a "+" prefix and an is required trait

  • "slurpy" -- i.e. an array or hash that consumes the rest of the actual parameters -- with a "*" before the variable name

Note that any given subroutine can either optional positional parameters or named parameters or a slurpy parameter. As a special exception, named parameters may be followed by a slurpy hash; the hash will contain all the key/value pairs other than the ones used for named parameters. Other combinations are not legal due to limitations of Perl 5 parameter conventions.

SUPPORTED TYPES

Perl6::Subs knows how to validate the following Perl 6 fundamental types:

str:

Any defined scalar. (Note: There is no test for not being a reference; given Perl 5's overloading facility, a reference may actually have a useful string value if you go ahead and use it.)

num:

A defined scalar that passes &Scalar::Util::looks_like_number.

int:

A num with no fractional part.

ref:

Any reference value.

bool:

Any defined scalar.

Perl6::Subs knows how to validate the following Perl 6 object types (but note that while Perl 6 considers all these to be objects, Perl 5 generally does not):

Any:

Any value, including undef.

Str:

Any scalar value, including undef. (For Perl6::Subs, this is a synonym for Any.)

Num:

A num, or undef.

Int:

An int, or undef.

Ref:

A reference value, or undef.

Array:

An array reference, or undef.

Hash:

A hash reference, or undef.

Code:

A code (subroutine) reference, or undef.

Rule:

A regexp reference (qr//), or undef.

IO:

An IO handle (e.g. *STDOUT{IO}, or a glob (e.g. *STDOUT), or a glob reference (e.g. \*STDOUT), or undef. Note that autovivified file handles work here, as they are references to blessed globs.

Glob:

A glob value (e.g. *STDOUT), or undef.

GlobRef:

A glob reference (e.g. \*STDOUT), or undef.

Any other bareword used as a type is assumed to name a user-defined class. A parameter so typed must satisfy UNIVERSAL::isa() of that class, or be undef.

CAVEATS

Avoid variable named after Perl quoting operators.

Do not use parameter names that turn into Perl quoting operators when their sigils are stripped: "$y", "$m", "@tr", "@q", etc. If you do so, Filter::Simple will be fooled into thinking large parts of your program are quoted strings, and large parts of your code may go unfiltered.

Parameters are not aliased; is copy is the default.

In Perl 6, formal parameters are usually read-only aliases for the actual parameter values. Parameters with the is rw trait are writeable aliases, and parameters with the is copy trait are writeable copies.

Perl6::Subs defaults to is copy semantics for efficiency reasons. Given that we're working on top of Perl 5, this is unlikely to change. Read-only aliasing is not a Perl 5 feature; to provide its semantics would currently require tying, and that's just too slow for us to make it the default. On the other hand, support for is rw may someday be provided via Lexical::Alias.

No Perl 5 prototypes.

The Perl 5 code produced by this source filter never includes Perl 5 prototypes for the functions with Perl 6 prototypes. This is a design decision driven mostly by its intended usage: creating object-oriented Perl code. Method calls in Perl 5 always ignore prototypes. And if you don't know what a Perl5 prototype is, exactly, defining it can be a tricky thing.

I suspect that if we ever add this feature, it will be as an additional function attribute:

sub foo (Int $x) is perl5_prototype($) { ... }

TODO

  • Some missing Perl 6 features that would be helpful in Perl 5 code:

    • Junction types (e.g. Foo | Bar)

    • Default parameter values (e.g. Int +$pos = 0)

    • Parameter traits and the features they enable (e.g. Int +$pos is required. (Perl6::Subs doe parse parameter traits, but it then proceeds to ignore them.)

    • Perl 6 prototypes on sub declarations (as opposed to definitions).

    • Interspersed comments in sub definitions. If you include any comments from the "sub" keyword to the open brace of the sub body, bad things will happen. This bug should be easy to fix by using the "placeholder" regular expression provided so kindly by Damian.

  • The default invocant, currently $self, should be user-changable. But I'm not sure the best user interface. This would work:

    use Perl6::Subs invocant => '$this';

    And yet, would you really want to have to put that at the top of every module? You'd probably just start using $self. For a large project, something like this would be better:

    # MyProject.pm
    package MyProject;
    use Perl6::Subs::Defaults invocant => '$this';
  • There's a hook for support of Params::Validate: valid {}, which works syntatically just like where {}. As of this writing, it does nothing.

BUGS

This module is a source filter. Source filters always break. For example, the breakage caused by parameter names that turn into Perl quoting operators when their sigils are stripped may never be fixed.

Please report any other bugs or feature requests to bug-perl6-subs@rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Perl6-Subs. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

AUTHOR

Chip Salzenberg, <chip@pobox.com>

ACKNOWLEDGEMENTS

Thanks to Heath Market Science <hmsonline.com> for funding creation of this module. Thanks also to Larry, Damian, Allison, et al for Perl 6 subroutine syntax, and to Damian for Filter::Simple and Parse::RecDescent.

COPYRIGHT & LICENSE

Copyright 2005 Chip Salzenberg and Health Market Science.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA