One of the things I'm looking forward to in Perl6 is greatly improved
sub/method signatures.
I'm hoping that this will eliminate the need for anything like
Params::Validate, which IMO is a nasty hack to make up for a serious
weakness in Perl5.
I'm going to go over the various features in P::V and see if there are
equivalents in Perl6, and bring up any questions I have. I think this
will be interesting for folks still new to P6 (like myself) and existing
P::V users (I think there's a fair number, but maybe I flatter myself ;)
Mandatory vs. Optional Parameters
This is a pretty straightforward one in P6, I think. Parameters can be
marked as required with "is required" like this:
sub date ($year, ?$month, ?$day) # positional
sub date (+$year is required, +$month, +$day) #named
This is ok but frankly I'm not too keen on the fact that for positional
subs, the default is required, but for named params it's the other way
around.
Wouldn't it clearer to just use a leading "?+" for optional named params?
Default Values
sub date ($year, ?$month = 1, ?$day = 1)
sub date (+$year is required, +$month = 1, +$day = 1)
Again, nice and straightforward.
Type Validation, "isa", & "can"
Params::Validate allows for several ways to check the _value_ of a
parameter. One way is to specify a primitive type like "SCALAR" or
"ARRAYREF". In P6 we have that with this:
sub date (Scalar +$year is required, ...)
I'm not sure is "Scalar" is a valid type though, but that's ok because we
have better types built in. In this case we should really use "Int" for a
year.
P::V also allows one to specify a class membership ("isa)" or one or more
methods ("can") a given object/class must have. In Perl6 we can just
specify a class:
sub transmit (Receiver $receiver)
If I understand this correctly, Receiver is a role here, and one that many
different classes may use/implement. This basically combines the isa &
can concepts. Instead of specifying required _methods_, we specify the
role, which seems conceptually cleaner anyway.
Regexes and Callbacks
P::V lets you validate a value based on a regex or one or more callbacks.
I think these can be replaced with subtypes, which is one of the most
exciting new P6 features (for me).
So instead of this (Perl5 P::V):
{ size => { callbacks =>
{ 'is a valid month' => sub { $_[0] >= 1 && $_[0] <= 12 }
we can now do this:
my subtype Month where { 1 <= $^s <= 12 }
This is so freaking awesome!
Then we just reference the subtype in our sub declaration:
sub date { $year, Month ?$month = 1, Day ?$day = 1 }
Subtypes can also be defined as regexes:
my subtype PerlIdentifier where / <+<alpha>+[_]> <+<alpha>+<digit>+[_]>* /;
(not 100% sure on that rule but you get the idea)
Dependencies, Exclusions, and "Require one-of"
With P::V I can do this:
{ credit_card_number =>
{ optional => 1,
depends => [ 'credit_card_expiration', 'credit_card_holder_name' ] },
credit_card_expiration => { optional => 1 },
credit_card_holder_name => { optional => 1 },
}
I have no idea how I might do this in Perl6, but I would love to see it
supported as part of parameter declarations
Similarly, something I've wanted to add to P::V is exclusions:
{ credit_card_number =>
{ optional => 1,
excludes => [ 'ach_bank_account_number' ] },
}
Another thing that would be really nice would be to require one of a set
of parameters, or one set out of multiple sets, so we could say "we need
credit card info _or_ bank account info".
For example, with the examples above, I probably want to require _either_
a credit card number _or_ a bank account number. Providing both is an
error, but so is not providing either.
Again, no idea how to do this in Perl6, but it seems like something that
could be supported via sub declarations
Since all of these can be checked at compile time (sometimes), it seems
like they'd be useful parts of the language, as opposed to something
user-created. Of course, I understand that there will be more ways to
mess with the compilation in Perl6.
Transformations
Another potential future feature for P::V is the ability to specify some
sort of transformation callback for a parameter. This is handy if you
want to be flexible in what inputs you take, but not explicitly write code
for all cases:
{ color => { regex => qr/^(?:green|blue|red)$/i,
transform => sub { lc $_[0] } }
}
I suspect that this could be implemented by a user-provide trait like "is
transformed":
sub print_error ($color where m:i/^ [green | blue | red] $/ is transformed {
lc })
Presumably this can be done with the existing language. It doesn't add
anything at compile time, so it really doesn't need to be part of the
language.
Anyway, I'd love to hear feedback on this. What did I get right? What
did I get wrong? Did I miss a more elegant way to do something? What
other types of param validation do other folks use/want to see?
-dave
/*===================================================
VegGuide.Org www.BookIRead.com
Your guide to all that's veg. My book blog
===================================================*/