rewrite attribute validation regex to check everything
[p5sagit/Function-Parameters.git] / lib / Function / Parameters.pm
1 package Function::Parameters;
2
3 use v5.14.0;
4
5 use warnings;
6
7 use Carp qw(confess);
8
9 use XSLoader;
10 BEGIN {
11         our $VERSION = '1.0103_01';
12         our $XS_VERSION = $VERSION;
13         $VERSION = eval $VERSION;
14         XSLoader::load;
15 }
16
17 sub _assert_valid_identifier {
18         my ($name, $with_dollar) = @_;
19         my $bonus = $with_dollar ? '\$' : '';
20         $name =~ /^${bonus}[^\W\d]\w*\z/
21                 or confess qq{"$name" doesn't look like a valid identifier};
22 }
23
24 sub _assert_valid_attributes {
25         my ($attrs) = @_;
26         $attrs =~ m{
27                 ^ \s*+
28                 : \s*+
29                 (?&ident) (?! [^\s:(] ) (?&param)?+ \s*+
30                 (?:
31                         (?: : \s*+ )?
32                         (?&ident) (?! [^\s:(] ) (?&param)?+ \s*+
33                 )*+
34                 \z
35
36                 (?(DEFINE)
37                         (?<ident>
38                                 [^\W\d]
39                                 \w*+
40                         )
41                         (?<param>
42                                 \(
43                                 [^()\\]*+
44                                 (?:
45                                         (?:
46                                                 \\ .
47                                         |
48                                                 (?&param)
49                                         )
50                                         [^()\\]*+
51                                 )*+
52                                 \)
53                         )
54                 )
55         }sx or confess qq{"$attrs" doesn't look like valid attributes};
56 }
57
58 my @bare_arms = qw(function method);
59 my %type_map = (
60         function => {
61                 name => 'optional',
62                 default_arguments => 1,
63                 check_argument_count => 0,
64                 named_parameters => 1,
65                 types => 1,
66         },
67         method   => {
68                 name => 'optional',
69                 default_arguments => 1,
70                 check_argument_count => 0,
71                 named_parameters => 1,
72                 types => 1,
73                 attrs => ':method',
74                 shift => '$self',
75                 invocant => 1,
76         },
77         classmethod   => {
78                 name => 'optional',
79                 default_arguments => 1,
80                 check_argument_count => 0,
81                 named_parameters => 1,
82                 types => 1,
83                 attributes => ':method',
84                 shift => '$class',
85                 invocant => 1,
86         },
87 );
88 for my $k (keys %type_map) {
89         $type_map{$k . '_strict'} = {
90                 %{$type_map{$k}},
91                 check_argument_count => 1,
92         };
93 }
94
95 sub import {
96         my $class = shift;
97
98         if (!@_) {
99                 @_ = {
100                         fun => 'function',
101                         method => 'method',
102                 };
103         }
104         if (@_ == 1 && $_[0] eq ':strict') {
105                 @_ = {
106                         fun => 'function_strict',
107                         method => 'method_strict',
108                 };
109         }
110         if (@_ == 1 && ref($_[0]) eq 'HASH') {
111                 @_ = map [$_, $_[0]{$_}], keys %{$_[0]};
112         }
113
114         my %spec;
115
116         my $bare = 0;
117         for my $proto (@_) {
118                 my $item = ref $proto
119                         ? $proto
120                         : [$proto, $bare_arms[$bare++] || confess(qq{Don't know what to do with "$proto"})]
121                 ;
122                 my ($name, $proto_type) = @$item;
123                 _assert_valid_identifier $name;
124
125                 unless (ref $proto_type) {
126                         # use '||' instead of 'or' to preserve $proto_type in the error message
127                         $proto_type = $type_map{$proto_type}
128                                 || confess qq["$proto_type" doesn't look like a valid type (one of ${\join ', ', sort keys %type_map})];
129                 }
130
131                 my %type = %$proto_type;
132                 my %clean;
133
134                 $clean{name} = delete $type{name} || 'optional';
135                 $clean{name} =~ /^(?:optional|required|prohibited)\z/
136                         or confess qq["$clean{name}" doesn't look like a valid name attribute (one of optional, required, prohibited)];
137
138                 $clean{shift} = delete $type{shift} || '';
139                 _assert_valid_identifier $clean{shift}, 1 if $clean{shift};
140
141                 $clean{attrs} = join ' ', map delete $type{$_} || (), qw(attributes attrs);
142                 _assert_valid_attributes $clean{attrs} if $clean{attrs};
143                 
144                 $clean{default_arguments} =
145                         exists $type{default_arguments}
146                         ? !!delete $type{default_arguments}
147                         : 1
148                 ;
149                 $clean{check_argument_count} = !!delete $type{check_argument_count};
150                 $clean{invocant} = !!delete $type{invocant};
151                 $clean{named_parameters} = !!delete $type{named_parameters};
152                 $clean{types} = !!delete $type{types};
153
154                 %type and confess "Invalid keyword property: @{[keys %type]}";
155
156                 $spec{$name} = \%clean;
157         }
158         
159         for my $kw (keys %spec) {
160                 my $type = $spec{$kw};
161
162                 my $flags =
163                         $type->{name} eq 'prohibited' ? FLAG_ANON_OK :
164                         $type->{name} eq 'required' ? FLAG_NAME_OK :
165                         FLAG_ANON_OK | FLAG_NAME_OK
166                 ;
167                 $flags |= FLAG_DEFAULT_ARGS if $type->{default_arguments};
168                 $flags |= FLAG_CHECK_NARGS | FLAG_CHECK_TARGS if $type->{check_argument_count};
169                 $flags |= FLAG_INVOCANT if $type->{invocant};
170                 $flags |= FLAG_NAMED_PARAMS if $type->{named_parameters};
171                 $flags |= FLAG_TYPES_OK if $type->{types};
172                 $^H{HINTK_FLAGS_ . $kw} = $flags;
173                 $^H{HINTK_SHIFT_ . $kw} = $type->{shift};
174                 $^H{HINTK_ATTRS_ . $kw} = $type->{attrs};
175                 $^H{+HINTK_KEYWORDS} .= "$kw ";
176         }
177 }
178
179 sub unimport {
180         my $class = shift;
181
182         if (!@_) {
183                 delete $^H{+HINTK_KEYWORDS};
184                 return;
185         }
186
187         for my $kw (@_) {
188                 $^H{+HINTK_KEYWORDS} =~ s/(?<![^ ])\Q$kw\E //g;
189         }
190 }
191
192
193 our %metadata;
194
195 sub _register_info {
196         my (
197                 $key,
198                 $declarator,
199                 $invocant,
200                 $invocant_type,
201                 $positional_required,
202                 $positional_optional,
203                 $named_required,
204                 $named_optional,
205                 $slurpy,
206                 $slurpy_type,
207         ) = @_;
208
209         my $info = {
210                 declarator => $declarator,
211                 invocant => defined $invocant ? [$invocant, $invocant_type] : undef,
212                 slurpy   => defined $slurpy   ? [$slurpy  , $slurpy_type  ] : undef,
213                 positional_required => $positional_required,
214                 positional_optional => $positional_optional,
215                 named_required => $named_required,
216                 named_optional => $named_optional,
217         };
218
219         $metadata{$key} = $info;
220 }
221
222 sub _mkparam1 {
223         my ($pair) = @_;
224         my ($v, $t) = @{$pair || []} or return undef;
225         Function::Parameters::Param->new(
226                 name => $v,
227                 type => $t,
228         )
229 }
230
231 sub _mkparams {
232         my @r;
233         while (my ($v, $t) = splice @_, 0, 2) {
234                 push @r, Function::Parameters::Param->new(
235                         name => $v,
236                         type => $t,
237                 );
238         }
239         \@r
240 }
241
242 sub info {
243         my ($func) = @_;
244         my $key = _cv_root $func or return undef;
245         my $info = $metadata{$key} or return undef;
246         require Function::Parameters::Info;
247         Function::Parameters::Info->new(
248                 keyword => $info->{declarator},
249                 invocant => _mkparam1($info->{invocant}),
250                 slurpy => _mkparam1($info->{slurpy}),
251                 (map +("_$_" => _mkparams @{$info->{$_}}), glob '{positional,named}_{required,optional}')
252         )
253 }
254
255 'ok'
256
257 __END__
258
259 =encoding UTF-8
260
261 =head1 NAME
262
263 Function::Parameters - subroutine definitions with parameter lists
264
265 =head1 SYNOPSIS
266
267  use Function::Parameters qw(:strict);
268  
269  # simple function
270  fun foo($bar, $baz) {
271    return $bar + $baz;
272  }
273  
274  # function with prototype
275  fun mymap($fun, @args)
276    :(&@)
277  {
278    my @res;
279    for (@args) {
280      push @res, $fun->($_);
281    }
282    @res
283  }
284  
285  print "$_\n" for mymap { $_ * 2 } 1 .. 4;
286  
287  # method with implicit $self
288  method set_name($name) {
289    $self->{name} = $name;
290  }
291  
292  # method with explicit invocant
293  method new($class: %init) {
294    return bless { %init }, $class;
295  }
296  
297  # function with optional parameters
298  fun search($haystack, $needle = qr/^(?!)/, $offset = 0) {
299    ...
300  }
301  
302  # method with named parameters
303  method resize(:$width, :$height) {
304    $self->{width}  = $width;
305    $self->{height} = $height;
306  }
307  
308  $obj->resize(height => 4, width => 5);
309  
310  # function with named optional parameters
311  fun search($haystack, :$needle = qr/^(?!)/, :$offset = 0) {
312    ...
313  }
314  
315  my $results = search $text, offset => 200;
316
317 =head1 DESCRIPTION
318
319 This module extends Perl with keywords that let you define functions with
320 parameter lists. It uses Perl's L<keyword plugin|perlapi/PL_keyword_plugin>
321 API, so it works reliably and doesn't require a source filter.
322
323 =head2 Basics
324
325 The anatomy of a function (as recognized by this module):
326
327 =over
328
329 =item 1.
330
331 The keyword introducing the function.
332
333 =item 2.
334
335 The function name (optional).
336
337 =item 3.
338
339 The parameter list (optional).
340
341 =item 4.
342
343 The prototype (optional).
344
345 =item 5.
346
347 The attribute list (optional).
348
349 =item 6.
350
351 The function body.
352
353 =back
354
355 Example:
356
357   # (1)   (2) (3)      (4)   (5)     (6)
358     fun   foo ($x, $y) :($$) :lvalue { ... }
359  
360   #         (1) (6)
361     my $f = fun { ... };
362
363 In the following section I'm going to describe all parts in order from simplest to most complex.
364
365 =head3 Body
366
367 This is just a normal block of statements, as with L<C<sub>|perlsub>. No surprises here.
368
369 =head3 Name
370
371 If present, it specifies the name of the function being defined. As with
372 L<C<sub>|perlsub>, if a name is present, the whole declaration is syntactically
373 a statement and its effects are performed at compile time (i.e. at runtime you
374 can call functions whose definitions only occur later in the file). If no name
375 is present, the declaration is an expression that evaluates to a reference to
376 the function in question. No surprises here either.
377
378 =head3 Attributes
379
380 Attributes are relatively unusual in Perl code, but if you want them, they work
381 exactly the same as with L<C<sub>|perlsub/Subroutine-Attributes>.
382
383 =head3 Prototype
384
385 As with L<C<sub>|perlsub/Prototypes>, a prototype, if present, contains hints as to how
386 the compiler should parse calls to this function. This means prototypes have no
387 effect if the function call is compiled before the function declaration has
388 been seen by the compiler or if the function to call is only determined at
389 runtime (e.g. because it's called as a method or through a reference).
390
391 With L<C<sub>|perlsub>, a prototype comes directly after the function name (if
392 any). C<Function::Parameters> reserves this spot for the
393 L<parameter list|/"Parameter list">. To specify a prototype, put it as the
394 first attribute (e.g. C<fun foo :(&$$)>). This is syntactically unambiguous
395 because normal L<attributes|/Attributes> need a name after the colon.
396
397 =head3 Parameter list
398
399 The parameter list is a list of variables enclosed in parentheses, except it's
400 actually a bit more complicated than that. A parameter list can include the
401 following 6 parts, all of which are optional:
402
403 =over
404
405 =item 1. Invocant
406
407 This is a scalar variable followed by a colon (C<:>) and no comma. If an
408 invocant is present in the parameter list, the first element of
409 L<C<@_>|perlvar/@ARG> is automatically L<C<shift>ed|perlfunc/shift> off and
410 placed in this variable. This is intended for methods:
411
412   method new($class: %init) {
413     return bless { %init }, $class;
414   }
415
416   method throw($self:) {
417     die $self;
418   }
419
420 =item 2. Required positional parameters
421
422 The most common kind of parameter. This is simply a comma-separated list of
423 scalars, which are filled from left to right with the arguments that the caller
424 passed in:
425
426   fun add($x, $y) {
427     return $x + $y;
428   }
429   
430   say add(2, 3);  # "5"
431
432 =item 3. Optional positional parameters
433
434 Parameters can be marked as optional by putting an equals sign (C<=>) and an
435 expression (the "default argument") after them. If no corresponding argument is
436 passed in by the caller, the default argument will be used to initialize the
437 parameter:
438
439   fun scale($base, $factor = 2) {
440     return $base * $factor;
441   }
442  
443   say scale(3, 5);  # "15"
444   say scale(3);     # "6"
445
446 The default argument is I<not> cached. Every time a function is called with
447 some optional arguments missing, the corresponding default arguments are
448 evaluated from left to right. This makes no difference for a value like C<2>
449 but it is important for expressions with side effects, such as reference
450 constructors (C<[]>, C<{}>) or function calls.
451
452 Default arguments see not only the surrounding lexical scope of their function
453 but also any preceding parameters. This allows the creation of dynamic defaults
454 based on previous arguments:
455
456   method set_name($self: $nick = $self->default_nick, $real_name = $nick) {
457     $self->{nick} = $nick;
458     $self->{real_name} = $real_name;
459   }
460  
461   $obj->set_name("simplicio");  # same as: $obj->set_name("simplicio", "simplicio");
462
463 Because default arguments are actually evaluated as part of the function body,
464 you can also do silly things like this:
465
466   fun foo($n = return "nope") {
467     "you gave me $n"
468   }
469  
470   say foo(2 + 2);  # "you gave me 4"
471   say foo();       # "nope"
472
473 =item 4. Required named parameters
474
475 By putting a colon (C<:>) in front of a parameter you can make it named
476 instead of positional:
477
478   fun rectangle(:$width, :$height) {
479     ...
480   }
481  
482   rectangle(width => 2, height => 5);
483   rectangle(height => 5, width => 2);  # same thing!
484
485 That is, the caller must specify a key name in addition to the value, but in
486 exchange the order of the arguments doesn't matter anymore. As with hash
487 initialization, you can specify the same key multiple times and the last
488 occurrence wins:
489
490   rectangle(height => 1, width => 2, height => 2, height => 5;
491   # same as: rectangle(width => 2, height => 5);
492
493 You can combine positional and named parameters as long as the positional
494 parameters come first:
495
496   fun named_rectangle($name, :$width, :$height) {
497     ...
498   }
499  
500   named_rectangle("Avocado", width => 0.5, height => 1.2);
501
502 =item 5. Optional named parameters
503
504 As with positional parameters, you can make named parameters optional by
505 specifying a default argument after an equals sign (C<=>):
506
507   fun rectangle(:$width, :$height, :$color = "chartreuse") {
508     ...
509   }
510  
511   rectangle(height => 10, width => 5);
512   # same as: rectangle(height => 10, width => 5, color => "chartreuse");
513
514 =cut
515
516 =pod
517   
518   fun get($url, :$cookie_jar = HTTP::Cookies->new(), :$referrer = $url) {
519     ...
520   }
521
522   my $data = get "http://www.example.com/", referrer => undef;  # overrides $referrer = $url
523
524 The above example shows that passing any value (even C<undef>) will override
525 the default argument.
526
527 =item 6. Slurpy parameter
528
529 Finally you can put an array or hash in the parameter list, which will gobble
530 up the remaining arguments (if any):
531
532   fun foo($x, $y, @rest) { ... }
533  
534   foo "a", "b";            # $x = "a", $y = "b", @rest = ()
535   foo "a", "b", "c";       # $x = "a", $y = "b", @rest = ("c")
536   foo "a", "b", "c", "d";  # $x = "a", $y = "b", @rest = ("c", "d")
537
538 If you combine this with named parameters, the slurpy parameter will end up
539 containing all unrecognized keys:
540
541   fun bar(:$size, @whatev) { ... }
542  
543   bar weight => 20, size => 2, location => [0, -3];
544   # $size = 2, @whatev = ('weight', 20, 'location', [0, -3])
545
546 =back
547
548 Apart from the L<C<shift>|perlfunc/shift> performed by the L<invocant|/"1.
549 Invocant">, all of the above leave L<C<@_>|perlvar/@ARG> unchanged; and if you
550 don't specify a parameter list at all, L<C<@_>|perlvar/@ARG> is all you get.
551
552 =head3 Keyword
553
554 The keywords provided by C<Function::Parameters> are customizable. Since
555 C<Function::Parameters> is actually a L<pragma|perlpragma>, the provided
556 keywords have lexical scope. The following import variants can be used:
557
558 =over
559
560 =item C<use Function::Parameters ':strict'>
561
562 Provides the keywords C<fun> and C<method> (described below) and enables
563 argument checks so that calling a function and omitting a required argument (or
564 passing too many arguments) will throw an error.
565
566 =item C<use Function::Parameters>
567
568 Provides the keywords C<fun> and C<method> (described below) and enables
569 "lax" mode: Omitting a required argument sets it to C<undef> while excess
570 arguments are silently ignored.
571
572 =item C<< use Function::Parameters { KEYWORD1 => TYPE1, KEYWORD2 => TYPE2, ... } >>
573
574 Provides completely custom keywords as described by their types. A "type" is
575 either a string (one of the predefined types C<function>, C<method>,
576 C<classmethod>, C<function_strict>, C<method_strict>, C<classmethod_strict>) or
577 a reference to a hash with the following keys:
578
579 =over
580
581 =item C<name>
582
583 Valid values: C<optional> (default), C<required> (all functions defined with
584 this keyword must have a name), and C<prohibited> (functions defined with this
585 keyword must be anonymous).
586
587 =item C<shift>
588
589 Valid values: strings that look like scalar variables. This lets you specify a
590 default L<invocant|/"1. Invocant">, i.e. a function defined with this keyword
591 that doesn't have an explicit invocant in its parameter list will automatically
592 L<C<shift>|perlfunc/shift> its first argument into the variable specified here.
593
594 =item C<invocant>
595
596 Valid values: booleans. If you set this to a true value, the keyword will
597 accept L<invocants|/"1. Invocant"> in parameter lists; otherwise specifying
598 an invocant in a function defined with this keyword is a syntax error.
599
600 =item C<attributes>
601
602 Valid values: strings containing (source code for) attributes. This causes any
603 function defined with this keyword to have the specified
604 L<attributes|attributes> (in addition to any attributes specified in the
605 function definition itself).
606
607 =item C<default_arguments>
608
609 Valid values: booleans. This property is on by default; use
610 C<< default_arguments => 0 >> to turn it off. This controls whether optional
611 parameters are allowed. If it is turned off, using C<=> in parameter lists is
612 a syntax error.
613
614 =item C<check_argument_count>
615
616 Valid values: booleans. If turned on, functions defined with this keyword will
617 automatically check that they have been passed all required arguments and no
618 excess arguments. If this check fails, an exception will by thrown via
619 L<C<Carp::croak>|Carp>.
620
621 =back
622
623 The predefined type C<function> is equivalent to:
624
625  {
626    name => 'optional',
627    invocant => 0,
628    default_arguments => 1,
629    check_argument_count => 0,
630  }
631
632 These are all default values, so C<function> is also equivalent to C<{}>.
633
634 C<method> is equivalent to:
635
636  {
637    name => 'optional',
638    shift => '$self',
639    invocant => 1,
640    attributes => ':method',
641    default_arguments => 1,
642    check_argument_count => 0,
643  }
644
645
646 C<classmethod> is equivalent to:
647
648  {
649    name => 'optional',
650    shift => '$class',
651    invocant => 1,
652    attributes => ':method',
653    default_arguments => 1,
654    check_argument_count => 0,
655  }
656
657 C<function_strict>, C<method_strict>, and
658 C<classmethod_strict> are like C<function>, C<method>, and
659 C<classmethod>, respectively, but with C<< check_argument_count => 1 >>.
660
661 =back
662
663 Plain C<use Function::Parameters> is equivalent to
664 C<< use Function::Parameters { fun => 'function', method => 'method' } >>.
665
666 C<use Function::Parameters qw(:strict)> is equivalent to
667 C<< use Function::Parameters { fun => 'function_strict', method => 'method_strict' } >>.
668
669 =head2 Introspection
670
671 You can ask a function at runtime what parameters it has. This functionality is
672 available through the function C<Function::Parameters::info> (which is not
673 exported, so you have to call it by its full name). It takes a reference to a
674 function, and returns either C<undef> (if it knows nothing about the function)
675 or a L<Function::Parameters::Info> object describing the parameter list.
676
677 Note: This feature is implemented using L<Moo>, so you'll need to have L<Moo>
678 installed if you want to call C<Function::Parameters::info> (alternatively, if
679 L<Moose> is already loaded by the time C<Function::Parameters::info> is first
680 called, it will use that instead).
681
682 See L<Function::Parameters::Info> for examples.
683
684 =head2 Wrapping C<Function::Parameters>
685
686 If you want to write a wrapper around C<Function::Parameters>, you only have to
687 call its C<import> method. Due to its L<pragma|perlpragma> nature it always
688 affects the file that is currently being compiled.
689
690  package Some::Wrapper;
691  use Function::Parameters ();
692  sub import {
693    Function::Parameters->import;
694    # or Function::Parameters->import(@custom_import_args);
695  }
696
697 =head2 Experimental feature: Types
698
699 An experimental feature is now available: You can annotate parameters with
700 L<Moose types|Moose::Manual::Types>. That is, before each parameter you can put
701 a type specification consisting of identifiers (C<Foo>), unions (C<... | ...>),
702 and parametric types (C<...[...]>). Example:
703
704   fun foo(Int $n, ArrayRef[String | CodeRef] $cb) { ... }
705
706 If you do this, L<Moose> will be loaded automatically (if that hasn't happened
707 yet). These specifications are parsed and validated using
708 L<C<Moose::Util::TypeConstraints::find_or_parse_type_constraint>|Moose::Util::TypeConstraints/find_or_parse_type_constraint>.
709
710 If you are in "lax" mode, nothing further happens and the types are ignored. If
711 you are in "strict" mode, C<Function::Parameters> generates code to make sure
712 any values passed in conform to the type (via
713 L<< C<< $constraint->check($value) >>|Moose::Meta::TypeConstraint/$constraint->check($value) >>).
714
715 In addition, these type constraints are inspectable through the
716 L<Function::Parameters::Info> object returned by
717 L<C<Function::Parameters::info>|/Introspection>.
718
719 =head2 Experimental experimental feature: Type expressions
720
721 An even more experimental feature is the ability to specify arbitrary
722 expressions as types. The syntax for this is like the literal types described
723 above, but with an expression wrapped in parentheses (C<( EXPR )>). Example:
724
725   fun foo(('Int') $n, ($othertype) $x) { ... }
726
727 Every type expression must return either a string (which is resolved as for
728 literal types), or a L<type constraint object|Moose::Meta::TypeConstraint>
729 (providing C<check> and C<get_message> methods).
730
731 Note that these expressions are evaluated (once) at parse time (similar to
732 C<BEGIN> blocks), so make sure that any variables you use are set and any
733 functions you call are defined at parse time.
734
735 =head2 How it works
736
737 The module is actually written in L<C|perlxs> and uses
738 L<C<PL_keyword_plugin>|perlapi/PL_keyword_plugin> to generate opcodes directly.
739 However, you can run L<C<perl -MO=Deparse ...>|B::Deparse> on your code to see
740 what happens under the hood. In the simplest case (no argument checks, possibly
741 an L<invocant|/"1. Invocant">, required positional/slurpy parameters only), the
742 generated code corresponds to:
743
744   fun foo($x, $y, @z) { ... }
745   # ... turns into ...
746   sub foo { my ($x, $y, @z) = @_; sub foo; ... }
747
748   method bar($x, $y, @z) { ... }
749   # ... turns into ...
750   sub bar :method { my $self = shift; my ($x, $y, @z) = @_; sub bar; ... }
751
752 =head1 SUPPORT AND DOCUMENTATION
753
754 After installing, you can find documentation for this module with the
755 perldoc command.
756
757     perldoc Function::Parameters
758
759 You can also look for information at:
760
761 =over
762
763 =item MetaCPAN
764
765 L<https://metacpan.org/module/Function%3A%3AParameters>
766
767 =item RT, CPAN's request tracker
768
769 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Function-Parameters>
770
771 =item AnnoCPAN, Annotated CPAN documentation
772
773 L<http://annocpan.org/dist/Function-Parameters>
774
775 =item CPAN Ratings
776
777 L<http://cpanratings.perl.org/d/Function-Parameters>
778
779 =item Search CPAN
780
781 L<http://search.cpan.org/dist/Function-Parameters/>
782
783 =back
784
785 =head1 SEE ALSO
786
787 L<Function::Parameters::Info>
788
789 =head1 AUTHOR
790
791 Lukas Mai, C<< <l.mai at web.de> >>
792
793 =head1 COPYRIGHT & LICENSE
794
795 Copyright 2010-2013 Lukas Mai.
796
797 This program is free software; you can redistribute it and/or modify it
798 under the terms of either: the GNU General Public License as published
799 by the Free Software Foundation; or the Artistic License.
800
801 See http://dev.perl.org/licenses/ for more information.
802
803 =cut