version 1.0104
[p5sagit/Function-Parameters.git] / lib / Function / Parameters / Info.pm
1 package Function::Parameters::Info;
2
3 use v5.14.0;
4 use warnings;
5
6 our $VERSION = '0.04';
7
8 # If Moo isn't loaded yet but Moose is, avoid pulling in Moo and fall back to Moose
9 my $Moo;
10 BEGIN {
11         if ($INC{'Moose.pm'} && !$INC{'Moo.pm'}) {
12                 $Moo = 'Moose';
13         } else {
14                 require Moo;
15                 $Moo = 'Moo';
16         }
17         $Moo->import;
18 }
19
20 {
21         package Function::Parameters::Param;
22
23         BEGIN { $Moo->import; }
24         use overload
25                 fallback => 1,
26                 '""'     => sub { $_[0]->name },
27         ;
28
29         has $_ => (is => 'ro') for qw(name type);
30
31         __PACKAGE__->meta->make_immutable;
32 }
33
34 my @pn_ro = glob '{positional,named}_{required,optional}';
35
36 for my $attr (qw[keyword invocant slurpy], map "_$_", @pn_ro) {
37         has $attr => (
38                 is => 'ro',
39         );
40 }
41
42 for my $gen (join "\n", map "sub $_ { \@{\$_[0]->_$_} }", @pn_ro) {
43         eval "$gen\n1" or die $@;
44 }
45
46 sub args_min {
47         my $self = shift;
48         my $r = 0;
49         $r++ if defined $self->invocant;
50         $r += $self->positional_required;
51         $r += $self->named_required * 2;
52         $r
53 }
54
55 sub args_max {
56         my $self = shift;
57         return 0 + 'Inf' if defined $self->slurpy || $self->named_required || $self->named_optional;
58         my $r = 0;
59         $r++ if defined $self->invocant;
60         $r += $self->positional_required;
61         $r += $self->positional_optional;
62         $r
63 }
64
65 __PACKAGE__->meta->make_immutable;
66
67 'ok'
68
69 __END__
70
71 =encoding UTF-8
72
73 =head1 NAME
74
75 Function::Parameters::Info - Information about parameter lists
76
77 =head1 SYNOPSIS
78
79   use Function::Parameters;
80   
81   fun foo($x, $y, :$hello, :$world = undef) {}
82   
83   my $info = Function::Parameters::info \&foo;
84   my $p0 = $info->invocant;             # undef
85   my @p1 = $info->positional_required;  # ('$x', '$y')
86   my @p2 = $info->positional_optional;  # ()
87   my @p3 = $info->named_required;       # ('$hello')
88   my @p4 = $info->named_optional;       # ('$world')
89   my $p5 = $info->slurpy;               # undef
90   my $min = $info->args_min;  # 4
91   my $max = $info->args_max;  # inf
92   
93   my $invocant = Function::Parameters::info(method () { 42 })->invocant;  # '$self'
94   
95   my $slurpy = Function::Parameters::info(fun {})->slurpy;  # '@_'
96
97 =head1 DESCRIPTION
98
99 L<C<Function::Parameters::info>|Function::Parameters/Introspection> returns
100 objects of this class to describe parameter lists of functions. The following
101 methods are available:
102
103 =head2 $info->invocant
104
105 Returns the name of the variable into which the first argument is
106 L<C<shift>|perlfunc/shift>ed automatically, or C<undef> if no such thing
107 exists. This will usually return C<'$self'> for methods.
108
109 =head2 $info->positional_required
110
111 Returns a list of the names of the required positional parameters (or a count
112 in scalar context).
113
114 =head2 $info->positional_optional
115
116 Returns a list of the names of the optional positional parameters (or a count
117 in scalar context).
118
119 =head2 $info->named_required
120
121 Returns a list of the names of the required named parameters (or a count
122 in scalar context).
123
124 =head2 $info->named_optional
125
126 Returns a list of the names of the optional named parameters (or a count
127 in scalar context).
128
129 =head2 $info->slurpy
130
131 Returns the name of the final array or hash that gobbles up all remaining
132 arguments, or C<undef> if no such thing exists.
133
134 As a special case, functions defined without an explicit parameter list (i.e.
135 without C<( )>) will return C<'@_'> here because they accept any number of
136 arguments.
137
138 =head2 $info->args_min
139
140 Returns the minimum number of arguments this function requires. This is
141 computed as follows: Invocant and required positional parameters count 1 each.
142 Optional parameters don't count. Required named parameters count 2 each (key +
143 value). Slurpy parameters don't count either because they accept empty lists.
144
145 =head2 $info->args_max
146
147 Returns the maximum number of arguments this function accepts. This is computed
148 as follows: If there is any named or slurpy parameter, the result is C<Inf>.
149 Otherwise the result is the sum of all invocant and positional parameters.
150
151 =head2 Experimental feature: Types
152
153 All the methods described above actually return parameter objects wherever the
154 description says "name". These objects have two methods: C<name>, which
155 returns the name of the parameter (as a plain string), and C<type>, which
156 returns the corresponding type constraint object (or undef if there was no type
157 specified).
158
159 This should be invisible if you don't use types because the objects also
160 L<overload|overload> stringification to call C<name>. That is, if you treat
161 parameter objects like strings, they behave like strings (i.e. their names).
162
163 =head1 SEE ALSO
164
165 L<Function::Parameters>
166
167 =head1 AUTHOR
168
169 Lukas Mai, C<< <l.mai at web.de> >>
170
171 =head1 COPYRIGHT & LICENSE
172
173 Copyright 2013 Lukas Mai.
174
175 This program is free software; you can redistribute it and/or modify it
176 under the terms of either: the GNU General Public License as published
177 by the Free Software Foundation; or the Artistic License.
178
179 See http://dev.perl.org/licenses/ for more information.
180
181 =cut