File Coverage

blib/lib/Sub/Lvalue.pm
Criterion Covered Total %
statement 53 53 100.0
branch 15 18 83.3
condition 2 3 66.6
subroutine 15 15 100.0
pod 2 2 100.0
total 87 91 95.6


line stmt bran cond sub pod time code
1             package Sub::Lvalue;
2              
3 3     3   39026 use warnings;
  3         3  
  3         76  
4 3     3   9 use strict;
  3         3  
  3         41  
5             #use ex::provide [qw(get set)];
6 3     3   10 use Carp;
  3         4  
  3         233  
7              
8             sub import {
9 2     2   13 my $pkg = shift;
10 2         4 my $pk = caller;
11 3     3   13 no strict 'refs';
  3         3  
  3         578  
12 2 50       6 for (@_ ? @_ : qw(get set)) {
13 4 50       17 defined &$_ or croak "$_ is not exported by $pk";
14 4         4 *{ $pk . '::' . $_ } = \&$_;
  4         1155  
15             }
16             }
17             =head1 NAME
18              
19             Sub::Lvalue - use lvalue subroutines with ease
20              
21             =head1 VERSION
22              
23             Version 0.01
24              
25             =cut
26              
27             our $VERSION = '0.01';
28              
29             =head1 SYNOPSIS
30              
31             Simply put get and set blocks at the end of your lvalue sub.
32             Please note, no comma or semicolon between statements are allowed (in case of semicolon only last statement will be take an action)
33              
34             use Sub::Lvalue;
35              
36             sub mysub : lvalue {
37             get {
38             return 'result for get';
39             }
40             set {
41             my $set_value = shift;
42             # ...
43             }
44             }
45              
46             mysub() = 'test'; # will invoke set block with argument 'test';
47             print mysub(); # will invoke get block without arguments. result will be returned to print;
48              
49             sub readonly : lvalue {
50             get {
51             return 'readonly value';
52             }
53             }
54            
55             print readonly(); # ok
56             readonly = 'test'; # fails
57              
58             sub writeonly : lvalue {
59             set {
60             my $set_value = shift;
61             # ...
62             }
63             }
64            
65             writeonly = 'test'; # ok
66             print writeonly(); # fails
67              
68             =head1 EXPORT
69              
70             There are 2 export functions: C and C. If you don't want to use export, you may use full names
71              
72             sub mysub : lvalue {
73             Sub::Lvalue::get {
74             return 'something';
75             }
76             Sub::Lvalue::set {
77             my $set_value = shift;
78             }
79             }
80              
81             =head1 FUNCTIONS
82              
83             =head2 set
84              
85             invoked with argument from right side
86              
87             =cut
88              
89             sub set (&;@) : lvalue {
90 8     8 1 1816 my $code = shift;
91 8 100       16 if (@_) {
92 2         4 tied($_[0])->set($code);
93             }else{
94 6         25 tie $_[0], 'Sub::Lvalue::tiecallback', undef, $code;
95             }
96 8         24 $_[0];
97             }
98              
99             =head2 get
100              
101             invoked without arguments. the returned value passed out
102              
103             =cut
104              
105             sub get (&;@) : lvalue {
106 8     8 1 247 my $code = shift;
107 8 100       14 if (@_) {
108 4         8 tied($_[0])->get($code);
109             }else{
110 4         11 tie $_[0], 'Sub::Lvalue::tiecallback', $code, undef;
111             }
112 8         26 $_[0];
113             }
114              
115             =head1 RENAMING
116              
117             From it's creation in 2009 till 2016 this module has name L.
118             In 2010 there were appeared module L.
119              
120             During years, there were semantic conflict between Lvalue and lvalue.
121             But this days PAUSE threats CPAN module names case insensitive that leads us to name conflict.
122              
123             After all, there is another great module L. As stated by its author, some part of it was inspired by C.
124              
125             I decided to eliminame original name L and to keep original source code if someone needs it under the name L
126              
127             =head1 AUTHOR
128              
129             Mons Anderson,
130              
131             =head1 BUGS
132              
133             None known
134              
135             =head1 COPYRIGHT & LICENSE
136              
137             Copyright 2009 Mons Anderson.
138              
139             This program is free software; you can redistribute it and/or modify it
140             under the same terms as Perl itself.
141              
142             =cut
143              
144             package Sub::Lvalue::tiecallback;
145              
146 3     3   11 use strict;
  3         5  
  3         51  
147 3     3   1161 use Sub::Name;
  3         1111  
  3         112  
148 3     3   13 use Carp;
  3         4  
  3         662  
149             our @CARP_NOT = 'lvalue';
150              
151             sub set {
152 2     2   3 $_[0]->[1] = $_[1];
153             }
154             sub get {
155 4     4   11 $_[0]->[0] = $_[1];
156             }
157              
158             sub TIESCALAR {
159 10     10   14 my ($pkg,$get,$set) = @_;
160 10         39 my $caller = (caller(2))[3];
161 10 100       33 subname $caller.':get',$get if $get;
162 10 100       41 subname $caller.':set',$set if $set;
163 10 50 66     34 $get or $set or croak "Neither set nor get passed";
164 10         27 return bless [$get,$set,$caller],$pkg;
165             }
166             sub FETCH {
167 5     5   41 my $self = shift;
168 5 100       79 defined $self->[0] or croak "$self->[2] is writeonly";
169 4         4 goto &{ $self->[0] };
  4         9  
170             }
171             sub STORE {
172 5     5   4 my $self = shift;
173 5 100       156 defined $self->[1] or croak "$self->[2] is readonly";
174 4         4 goto &{ $self->[1] };
  4         19  
175             }
176              
177             1;