]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
Document the initializer method in its own section
[perl/modules/Lexical-Types.git] / lib / Lexical / Types.pm
1 package Lexical::Types;
2
3 use 5.008;
4
5 use strict;
6 use warnings;
7
8 use Carp qw/croak/;
9
10 =head1 NAME
11
12 Lexical::Types - Extend the semantics of typed lexicals.
13
14 =head1 VERSION
15
16 Version 0.03
17
18 =cut
19
20 our $VERSION;
21 BEGIN {
22  $VERSION = '0.03';
23 }
24
25 =head1 SYNOPSIS
26
27     { package Str; }
28
29     {
30      package My::Types::Str;
31
32      sub new { bless { }, shift }
33     }
34
35     use Lexical::Types as => sub { 'My::Types::' . $_[0] => 'new' };
36
37     my Str $x; # $x is now a My::Types::Str object
38
39     {
40      package My::Types::Int;
41
42      sub TYPEDSCALAR { bless { }, shift }
43     }
44
45     use Lexical::Types;
46
47     use constant Int => 'My::Types::Int';
48
49     my Int $y; # $y is now a My::Types::Int object
50
51 =head1 DESCRIPTION
52
53 This pragma allows you to hook the execution of typed lexicals declarations (C<my Str $x>) by calling a configurable method in a configurable package at each run.
54 In particular, it can be used to automatically tie or bless typed lexicals whenever they are initialized.
55
56 Remind that for C<perl> to be able to parse C<my Str $x>, you need :
57
58 =over 4
59
60 =item *
61
62 either the C<Str> package to be defined ;
63
64 =item *
65
66 or for C<Str> to be a constant sub returning a valid defined package.
67
68 =back
69
70 so make sure you follow one of those two strategies to define your types.
71
72 This pragma is B<not> implemented with a source filter.
73
74 =cut
75
76 BEGIN {
77  require XSLoader;
78  XSLoader::load(__PACKAGE__, $VERSION);
79 }
80
81 =head1 FUNCTIONS
82
83 =head2 C<< import [ as => [ $prefix | $mangler ] ] >>
84
85 Magically called when writing C<use Lexical::Types>.
86 All the occurences of C<my Str $x> in the current lexical scope will be changed to call at each run a given method in a given package.
87 The method and package are determined by the parameter C<'as'> :
88
89 =over 4
90
91 =item *
92
93 If it's left unspecified, the C<TYPEDSCALAR> method in the C<Str> package will be called.
94
95     use Lexical::Types;
96     my Str $x; # calls Str->TYPEDSCALAR
97
98 =item *
99
100 If a plain scalar C<$prefix> is passed as the value, the C<TYPEDSCALAR> method in the C<${prefix}::Str> package will be used.
101
102     use Lexical::Types as => 'My::'; # or "as => 'My'"
103     my Str $x; # calls My::Str->TYPEDSCALAR
104
105 =item *
106
107 If the value given is a code reference C<$mangler>, it will be called at compile-time with arguments C<'Str'> and C<'TYPEDSCALAR'> and is expected to return :
108
109 =over 4
110
111 =item *
112
113 either an empty list, in which case the current typed lexical definition will be skipped (thus it won't be altered to trigger a run-time hook) ;
114
115     use Lexical::Types as => sub { return $_[0] =~ /Str/ ? @_ : () };
116     my Str $y; # calls Str->TYPEDSCALAR
117     my Int $x; # nothing special
118
119 =item *
120
121 or the desired package and method name, in that order (if any of those is C<undef>, the default value will be used instead).
122
123     use Lexical::Types as => sub { 'My', 'new_' . lc($_[0]) };
124     my Str $x; # the coderef indicates to call My->new_str
125
126 =back
127
128 =back
129
130 =cut
131
132 sub import {
133  shift;
134  my %args = @_;
135
136  my $hint;
137
138  my $as = delete $args{'as'};
139  if ($as) {
140   my $r = ref $as;
141   if ($r eq 'CODE') {
142    $hint = _tag($as);
143   } elsif (!$r) {
144    $as .= '::' if $as !~ /::$/;
145    $hint = _tag(sub { $as . $_[0] });
146   } else {
147    croak "Invalid $r reference for 'as'";
148   }
149  } else {
150   $hint = _tag(0);
151  }
152
153  $^H |= 0x020000;
154  # Yes, we store a coderef inside the hints hash, but that's just for compile
155  # time.
156  $^H{+(__PACKAGE__)} = $hint;
157 }
158
159 =head2 C<unimport>
160
161 Magically called when writing C<no Lexical::Types>.
162 Turns the pragma off.
163
164 =cut
165
166 sub unimport {
167  $^H{+(__PACKAGE__)} = undef;
168 }
169
170 =head1 RUN-TIME INITIALIZER METHOD
171
172 The initializer method receives an alias to the pad slot of the initialized lexical in C<$_[1]> and the original type name in C<$_[2]>.
173 You can either edit C<$_[1]> in place, in which case you should return an empty list, or return a new scalar that will be copied into the pad slot.
174
175     use Lexical::Types as => 'My';
176
177     my Str $x;
178
179     ...
180
181     sub My::Str::TYPEDSCALAR {
182      # $_[1] is an alias to $x, and $_[2] is 'Str'
183      ...
184     }
185
186 =head1 INTEGRATION
187
188 You can integrate L<Lexical::Types> in your module so that using it will provide types to your users without asking them to load either L<Lexical::Types> or the type classes manually.
189
190     package MyTypes;
191
192     BEGIN { require Lexical::Types; }
193
194     sub import {
195      eval 'package Str; package Int'; # The types you want to support
196      Lexical::Types->import(
197       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
198      );
199     }
200
201     sub unimport {
202      Lexical::Types->unimport;
203     }
204
205     sub new_str { ... }
206
207     sub new_int { ... }
208
209 =head1 CAVEATS
210
211 For C<perl> to be able to parse C<my Str $x>, you need :
212
213 =over 4
214
215 =item *
216
217 either the C<Str> package to be defined ;
218
219 =item *
220
221 or for C<Str> to be a constant sub returning a valid defined package.
222
223 =back
224
225 The restrictions on the type (being either a defined package name or a constant) apply even if you use the C<'as'> option to redirect to another package, and are unlikely to find a workaround as this happens deep inside the lexer - far from the reach of an extension.
226
227 Only one mangler or prefix can be in use at the same time in a given scope.
228
229 =head1 DEPENDENCIES
230
231 L<perl> 5.8, L<XSLoader>.
232
233 =head1 SEE ALSO
234
235 L<fields>.
236
237 L<Attribute::Handlers>.
238
239 =head1 AUTHOR
240
241 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
242
243 You can contact me by mail or on C<irc.perl.org> (vincent).
244
245 =head1 BUGS
246
247 Please report any bugs or feature requests to C<bug-lexical-types at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Lexical-Types>.  I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
248
249 =head1 SUPPORT
250
251 You can find documentation for this module with the perldoc command.
252
253     perldoc Lexical::Types
254
255 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Lexical-Types>.
256
257 =head1 ACKNOWLEDGEMENTS
258
259 Inspired by Ricardo Signes.
260
261 Thanks Florian Ragwitz for suggesting the use of constants for types.
262
263 =head1 COPYRIGHT & LICENSE
264
265 Copyright 2009 Vincent Pit, all rights reserved.
266
267 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
268
269 =cut
270
271 1; # End of Lexical::Types