]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
Settle for 'Str' as the main package example in the doc
[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.01
17
18 =cut
19
20 our $VERSION;
21 BEGIN {
22  $VERSION = '0.01';
23 }
24
25 =head1 SYNOPSIS
26
27     {
28      package Str;
29
30      sub TYPEDSCALAR { Some::String::Implementation->new }
31     }
32
33     use Lexical::Types;
34
35     my Str $x; # $x is now a Some::String::Implementation object
36
37 =head1 DESCRIPTION
38
39 This module allows you to hook the execution of typed lexicals declarations (C<my Str $x>).
40 In particular, it can be used to automatically tie or bless typed lexicals.
41
42 It is B<not> implemented with a source filter.
43
44 =cut
45
46 BEGIN {
47  require XSLoader;
48  XSLoader::load(__PACKAGE__, $VERSION);
49 }
50
51 =head1 FUNCTIONS
52
53 =head2 C<< import [ as => [ $prefix | $mangler ] ] >>
54
55 Magically called when writing C<use Lexical::Types>.
56 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.
57 The method and package are determined by the parameter C<as> :
58
59 =over 4
60
61 =item *
62
63 If it's left unspecified, the C<TYPEDSCALAR> method in the C<Str> package will be called.
64
65     use Lexical::Types;
66     my Str $x; # calls Str->TYPEDSCALAR
67
68 =item *
69
70 If a plain scalar C<$prefix> is passed as the value, the C<TYPEDSCALAR> method in the C<${prefix}::Str> package will be used.
71
72     use Lexical::Types as => 'My::'; # or "as => 'My'"
73     my Str $x; # calls My::Str->TYPEDSCALAR
74
75 =item *
76
77 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 :
78
79 =over 4
80
81 =item *
82
83 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) ;
84
85     use Lexical::Types as => sub { return $_[0] =~ /Str/ ? () : @_ };
86     my Str $x; # nothing special
87     my Int $y; # calls Int->TYPEDSCALAR
88
89 =item *
90
91 or the desired package and method name, in that order (if any of those is C<undef>, the default value will be used instead).
92
93     use Lexical::Types as => sub { 'My', 'new_' . lc($_[0]) };
94     my Str $x; # the coderef indicates to call My->new_str
95
96 =back
97
98 =back
99
100 The initializer method receives an alias to the pad entry of C<$x> in C<$_[1]> and the original type name (C<Str>) in C<$_[2]>.
101 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 C<$x>.
102
103 =cut
104
105 sub import {
106  shift;
107  my %args = @_;
108
109  my $hint;
110
111  my $as = delete $args{'as'};
112  if ($as) {
113   my $r = ref $as;
114   if ($r eq 'CODE') {
115    $hint = _tag($as);
116   } elsif (!$r) {
117    $as .= '::' if $as !~ /::$/;
118    $hint = _tag(sub { $as . $_[0] });
119   } else {
120    croak "Invalid $r reference for 'as'";
121   }
122  } else {
123   $hint = _tag(0);
124  }
125
126  $^H |= 0x020000;
127  # Yes, we store a coderef inside the hints hash, but that's just for compile
128  # time.
129  $^H{+(__PACKAGE__)} = $hint;
130 }
131
132 =head2 C<unimport>
133
134 Magically called when writing C<no Lexical::Types>.
135 Turns the module off.
136
137 =cut
138
139 sub unimport {
140  $^H{+(__PACKAGE__)} = undef;
141 }
142
143 =head1 INTEGRATION
144
145 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.
146
147     package MyTypes;
148
149     BEGIN { require Lexical::Types; }
150
151     sub import {
152      eval 'package Str; package Int'; # The types you want to support
153      Lexical::Types->import(
154       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
155      );
156     }
157
158     sub unimport {
159      Lexical::Types->unimport;
160     }
161
162     sub new_str { ... }
163
164     sub new_int { ... }
165
166 =head1 CAVEATS
167
168 For C<perl> to be able to parse C<my Str $x>, the package C<Str> must be defined somewhere, and this even if you use the C<as> option to redirect to another package.
169 It's unlikely to find a workaround, as this happens deep inside the lexer, far from the reach of an extension.
170
171 Only one mangler or prefix can be in use at the same time in a given scope.
172
173 =head1 DEPENDENCIES
174
175 L<perl> 5.8, L<XSLoader>.
176
177 =head1 SEE ALSO
178
179 L<fields>.
180
181 L<Attribute::Handlers>.
182
183 =head1 AUTHOR
184
185 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
186
187 You can contact me by mail or on C<irc.perl.org> (vincent).
188
189 =head1 BUGS
190
191 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.
192
193 =head1 SUPPORT
194
195 You can find documentation for this module with the perldoc command.
196
197     perldoc Lexical::Types
198
199 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Lexical-Types>.
200
201 =head1 ACKNOWLEDGEMENTS
202
203 Inspired by Ricardo Signes.
204
205 =head1 COPYRIGHT & LICENSE
206
207 Copyright 2009 Vincent Pit, all rights reserved.
208
209 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
210
211 =cut
212
213 1; # End of Lexical::Types