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