← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Thu Dec 15 15:23:56 2022
Reported on Thu Dec 15 15:27:02 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/MooX/HandlesVia.pm
StatementsExecuted 338 statements in 1.37ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
3611492µs10.5msMooX::HandlesVia::::process_hasMooX::HandlesVia::process_has
36315203µs72.6msMooX::HandlesVia::::hasMooX::HandlesVia::has
55564µs272µsMooX::HandlesVia::::importMooX::HandlesVia::import
11124µs26µsMooX::HandlesVia::::BEGIN@4MooX::HandlesVia::BEGIN@4
11118µs22µsMooX::HandlesVia::::BEGIN@25MooX::HandlesVia::BEGIN@25
1116µs19µsMooX::HandlesVia::::BEGIN@9MooX::HandlesVia::BEGIN@9
1114µs13µsMooX::HandlesVia::::BEGIN@26MooX::HandlesVia::BEGIN@26
1114µs38µsMooX::HandlesVia::::BEGIN@5MooX::HandlesVia::BEGIN@5
1112µs2µsMooX::HandlesVia::::BEGIN@8MooX::HandlesVia::BEGIN@8
1111µs1µsMooX::HandlesVia::::BEGIN@7MooX::HandlesVia::BEGIN@7
0000s0sMooX::HandlesVia::::__ANON__[:32]MooX::HandlesVia::__ANON__[:32]
0000s0sMooX::HandlesVia::::__ANON__[:84]MooX::HandlesVia::__ANON__[:84]
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package MooX::HandlesVia;
2# ABSTRACT: NativeTrait-like behavior for Moo.
311µs$MooX::HandlesVia::VERSION = '0.001009';
4237µs228µs
# spent 26µs (24+2) within MooX::HandlesVia::BEGIN@4 which was called: # once (24µs+2µs) by JSON::Schema::Modern::BEGIN@30 at line 4
use strict;
# spent 26µs making 1 call to MooX::HandlesVia::BEGIN@4 # spent 2µs making 1 call to strict::import
5215µs272µs
# spent 38µs (4+34) within MooX::HandlesVia::BEGIN@5 which was called: # once (4µs+34µs) by JSON::Schema::Modern::BEGIN@30 at line 5
use warnings;
# spent 38µs making 1 call to MooX::HandlesVia::BEGIN@5 # spent 34µs making 1 call to warnings::import
6
7222µs11µs
# spent 1µs within MooX::HandlesVia::BEGIN@7 which was called: # once (1µs+0s) by JSON::Schema::Modern::BEGIN@30 at line 7
use Moo ();
# spent 1µs making 1 call to MooX::HandlesVia::BEGIN@7
8214µs12µs
# spent 2µs within MooX::HandlesVia::BEGIN@8 which was called: # once (2µs+0s) by JSON::Schema::Modern::BEGIN@30 at line 8
use Moo::Role ();
# spent 2µs making 1 call to MooX::HandlesVia::BEGIN@8
9261µs232µs
# spent 19µs (6+13) within MooX::HandlesVia::BEGIN@9 which was called: # once (6µs+13µs) by JSON::Schema::Modern::BEGIN@30 at line 9
use Module::Runtime qw/require_module/;
# spent 19µs making 1 call to MooX::HandlesVia::BEGIN@9 # spent 13µs making 1 call to Module::Runtime::import
10
11# reserved hardcoded mappings for classname shortcuts.
1213µsmy %RESERVED = (
13 'Array' => 'Data::Perl::Collection::Array::MooseLike',
14 'Hash' => 'Data::Perl::Collection::Hash::MooseLike',
15 'String' => 'Data::Perl::String::MooseLike',
16 'Bool' => 'Data::Perl::Bool::MooseLike',
17 'Number' => 'Data::Perl::Number::MooseLike',
18 'Code' => 'Data::Perl::Code',
19);
2014µsmy %REVERSED = reverse %RESERVED;
21
22
# spent 272µs (64+208) within MooX::HandlesVia::import which was called 5 times, avg 54µs/call: # once (13µs+67µs) by JSON::Schema::Modern::BEGIN@30 at line 30 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (15µs+42µs) by JSON::Schema::Modern::Document::OpenAPI::BEGIN@24 at line 24 of JSON/Schema/Modern/Document/OpenAPI.pm # once (16µs+37µs) by OpenAPI::Modern::BEGIN@29 at line 29 of OpenAPI/Modern.pm # once (12µs+30µs) by JSON::Schema::Modern::Document::BEGIN@23 at line 23 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (8µs+32µs) by JSON::Schema::Modern::Result::BEGIN@19 at line 19 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm
sub import {
2354µs my ($class) = @_;
24
25232µs226µs
# spent 22µs (18+4) within MooX::HandlesVia::BEGIN@25 which was called: # once (18µs+4µs) by JSON::Schema::Modern::BEGIN@30 at line 25
no strict 'refs';
# spent 22µs making 1 call to MooX::HandlesVia::BEGIN@25 # spent 4µs making 1 call to strict::unimport
262319µs222µs
# spent 13µs (4+9) within MooX::HandlesVia::BEGIN@26 which was called: # once (4µs+9µs) by JSON::Schema::Modern::BEGIN@30 at line 26
no warnings 'redefine';
# spent 13µs making 1 call to MooX::HandlesVia::BEGIN@26 # spent 9µs making 1 call to warnings::unimport
27
2853µs my $target = caller;
29539µs58µs if (my $has = $target->can('has')) {
# spent 8µs making 5 calls to UNIVERSAL::can, avg 2µs/call
30
# spent 72.6ms (203µs+72.4) within MooX::HandlesVia::has which was called 36 times, avg 2.02ms/call: # 4 times (33µs+5.78ms) by JSON::Schema::Modern::Document::OpenAPI::has at line 6 of (eval 384)[Class/Method/Modifiers.pm:148], avg 1.45ms/call # 2 times (14µs+9.68ms) by JSON::Schema::Modern::BEGIN@34 at line 67 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm, avg 4.85ms/call # 2 times (10µs+2.46ms) by OpenAPI::Modern::has at line 6 of (eval 399)[Class/Method/Modifiers.pm:148], avg 1.23ms/call # once (6µs+9.87ms) by JSON::Schema::Modern::BEGIN@35 at line 79 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (7µs+8.88ms) by OpenAPI::Modern::BEGIN@26 at line 122 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (8µs+7.28ms) by OpenAPI::Modern::BEGIN@26 at line 650 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (10µs+3.22ms) by OpenAPI::Modern::BEGIN@26 at line 752 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (8µs+3.02ms) by OpenAPI::Modern::BEGIN@26 at line 936 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (7µs+2.98ms) by OpenAPI::Modern::BEGIN@26 at line 710 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (5µs+2.68ms) by JSON::Schema::Modern::BEGIN@35 at line 91 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (3µs+2.10ms) by JSON::Schema::Modern::BEGIN@35 at line 111 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (6µs+1.87ms) by JSON::Schema::Modern::BEGIN@35 at line 40 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (8µs+1.79ms) by OpenAPI::Modern::BEGIN@26 at line 968 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (8µs+1.06ms) by OpenAPI::Modern::BEGIN@26 at line 910 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (6µs+907µs) by JSON::Schema::Modern::BEGIN@35 at line 46 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (8µs+887µs) by OpenAPI::Modern::BEGIN@26 at line 57 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (4µs+886µs) by JSON::Schema::Modern::BEGIN@35 at line 48 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (7µs+844µs) by JSON::Schema::Modern::BEGIN@34 at line 39 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm # once (2µs+785µs) by JSON::Schema::Modern::BEGIN@34 at line 48 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm # once (4µs+701µs) by JSON::Schema::Modern::BEGIN@35 at line 94 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (5µs+648µs) by JSON::Schema::Modern::BEGIN@34 at line 72 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm # once (2µs+615µs) by OpenAPI::Modern::BEGIN@26 at line 70 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (3µs+578µs) by OpenAPI::Modern::BEGIN@26 at line 91 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (6µs+506µs) by JSON::Schema::Modern::BEGIN@35 at line 29 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (3µs+362µs) by OpenAPI::Modern::BEGIN@26 at line 72 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (4µs+359µs) by OpenAPI::Modern::BEGIN@26 at line 93 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (3µs+355µs) by JSON::Schema::Modern::BEGIN@34 at line 78 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Result.pm # once (4µs+337µs) by OpenAPI::Modern::BEGIN@26 at line 98 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (2µs+330µs) by OpenAPI::Modern::BEGIN@26 at line 103 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (4µs+320µs) by OpenAPI::Modern::BEGIN@26 at line 59 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (3µs+279µs) by OpenAPI::Modern::BEGIN@26 at line 78 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm
my $newsub = sub {
3136188µs7272.4ms $has->(process_has(@_));
# spent 31.8ms making 16 calls to JSON::Schema::Modern::has, avg 1.99ms/call # spent 16.0ms making 8 calls to JSON::Schema::Modern::Document::has, avg 2.00ms/call # spent 10.5ms making 36 calls to MooX::HandlesVia::process_has, avg 292µs/call # spent 8.17ms making 6 calls to Moo::has, avg 1.36ms/call # spent 5.84ms making 6 calls to JSON::Schema::Modern::Result::has, avg 974µs/call
3259µs };
33
34511µs585µs if (Moo::Role->is_role($target)) {
# spent 85µs making 5 calls to Moo::Role::is_role, avg 17µs/call
35 Moo::Role::_install_tracked($target, "has", $newsub);
36 }
37 else {
3859µs5115µs Moo::_install_tracked($target, "has", $newsub);
# spent 115µs making 5 calls to Moo::_Utils::_install_tracked, avg 23µs/call
39 }
40 }
41}
42
43
# spent 10.5ms (492µs+10.0) within MooX::HandlesVia::process_has which was called 36 times, avg 292µs/call: # 36 times (492µs+10.0ms) by MooX::HandlesVia::has at line 31, avg 292µs/call
sub process_has {
4436105µs my ($name, %opts) = @_;
453614µs my $handles = $opts{handles};
463684µs return ($name, %opts) if not $handles or ref $handles ne 'HASH';
47
481313µs if (my $via = delete $opts{handles_via}) {
49125µs $via = ref $via eq 'ARRAY' ? $via->[0] : $via;
50
51 # try to load the reserved mapping, if it exists, else the full name
521210µs $via = $RESERVED{$via} || $via;
531231µs129.95ms require_module($via);
# spent 9.95ms making 12 calls to Module::Runtime::require_module, avg 829µs/call
54
55 # clone handles for HandlesMoose support
561220µs my %handles_clone = %$handles;
57
581238µs while (my ($target, $delegation) = each %$handles) {
59 # if passed an array, handle the curry
6036168µs3678µs if (ref $delegation eq 'ARRAY') {
# spent 78µs making 36 calls to UNIVERSAL::can, avg 2µs/call
61 my ($method, @curry) = @$delegation;
62 if ($via->can($method)) {
63 $handles->{$target} = ['${\\'.$via.'->can("'.$method.'")}', @curry];
64 }
65 }
66 elsif (ref $delegation eq '') {
67 if ($via->can($delegation)) {
68 $handles->{$target} = '${\\'.$via.'->can("'.$delegation.'")}';
69 }
70 }
71 }
72
73 # install our support for moose upgrading of class/role
74 # we deleted the handles_via key above, but install it as a native trait
751236µs my $inflator = $opts{moosify};
76 $opts{moosify} = sub {
77 my ($spec) = @_;
78
79 $spec->{handles} = \%handles_clone;
80 $spec->{traits} = [$REVERSED{$via} || $via];
81
82 # pass through if needed
83 $inflator->($spec) if ref($inflator) eq 'CODE';
841230µs };
85 }
86
871345µs ($name, %opts);
88}
89
9014µs1;
91
92=pod
93
94=encoding UTF-8
95
96=head1 NAME
97
98MooX::HandlesVia - NativeTrait-like behavior for Moo.
99
100=head1 VERSION
101
102version 0.001009
103
104=head1 SYNOPSIS
105
106 {
107 package Hashy;
108 use Moo;
109 use MooX::HandlesVia;
110
111 has hash => (
112 is => 'rw',
113 handles_via => 'Hash',
114 handles => {
115 get_val => 'get',
116 set_val => 'set',
117 all_keys => 'keys'
118 }
119 );
120 }
121
122 my $h = Hashy->new(hash => { a => 1, b => 2});
123
124 $h->get_val('b'); # 2
125
126 $h->set_val('a', 'BAR'); # sets a to BAR
127
128 my @keys = $h->all_keys; # returns a, b
129
130=head1 DESCRIPTION
131
132MooX::HandlesVia is an extension of Moo's 'handles' attribute functionality. It
133provides a means of proxying functionality from an external class to the given
134atttribute. This is most commonly used as a way to emulate 'Native Trait'
135behavior that has become commonplace in Moose code, for which there was no Moo
136alternative.
137
138=head1 SHORTCOMINGS
139
140Due to current Moo implementation details there are some deficiencies in how
141MooX::HandlesVia in comparison to what you would expect from Moose native
142traits.
143
144=over 4
145
146=item * methods delegated via the Moo 'handles' interface are passed the
147attribue value directly. and there is no way to access the parent class. This
148means if an attribute is updated any triggers or type coercions B<WILL NOT>
149fire.
150
151=item * Moo attribute method delegations are passed the attribute value. This
152is fine for references (objects, arrays, hashrefs..) it means simple scalar
153types are B<READ ONLY>. This unfortunately means Number, String, Counter, Bool
154cannot modify the attributes value, rendering them largely useless.
155
156=back
157
158If these are issues for you, consider L<Sub::HandlesVia>, which uses a
159different architecture, respecting triggers and coercions, and allowing
160read-write access to non-reference values. It should be possible to use
161Sub::HandlesVia as a drop-in replacement for MooX::HandlesVia.
162
163=head1 PROVIDED INTERFACE/FUNCTIONS
164
165=over 4
166
167=item B<process_has(@_)>
168
169MooX::HandlesVia preprocesses arguments passed to has() attribute declarations
170via the process_has function. In a given Moo class, If 'handles_via' is set to
171a ClassName string, and 'handles' is set with a hashref mapping of desired moo
172class methods that should map to ClassName methods, process_has() will create
173the appropriate binding to create the mapping IF ClassName provides that named
174method.
175
176 has options => (
177 is => 'rw',
178 handles_via => 'Array',
179 handles => {
180 mixup => 'shuffle',
181 unique_options => 'uniq',
182 all_options => 'elements'
183 }
184 );
185
186=back
187
188The following handles_via keywords are reserved as shorthand for mapping to
189L<Data::Perl>:
190
191=over 4
192
193=item * B<Hash> maps to L<Data::Perl::Collection::Hash::MooseLike>
194
195=item * B<Array> maps to L<Data::Perl::Collection::Array::MooseLike>
196
197=item * B<String> maps to L<Data::Perl::String::MooseLike>
198
199=item * B<Number> maps to L<Data::Perl::Number::MooseLike>
200
201=item * B<Bool> maps to L<Data::Perl::Bool::MooseLike>
202
203=item * B<Code> maps to L<Data::Perl::Code>
204
205=back
206
207=head1 SEE ALSO
208
209=over 4
210
211=item * L<Moo>
212
213=item * L<MooX::late>
214
215=item * L<Sub::HandlesVia>
216
217=back
218
219=head1 ORIGINAL AUTHOR
220
221Matthew Phillips <mattp@cpan.org>
222
223=head1 AUTHOR
224
225Toby Inkster <tobyink@cpan.org>
226
227=head1 COPYRIGHT AND LICENSE
228
229This software is copyright (c) 2020 by Matthew Phillips <mattp@cpan.org>.
230
231This is free software; you can redistribute it and/or modify it under
232the same terms as the Perl 5 programming language system itself.
233
234=cut
235
236__END__