File Coverage

lib/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 lvalue;
2              
3 3     3   93726 use warnings;
  3         7  
  3         97  
4 3     3   17 use strict;
  3         5  
  3         100  
5             #use ex::provide [qw(get set)];
6 3     3   14 use Carp;
  3         10  
  3         320  
7              
8             sub import {
9 2     2   17 my $pkg = shift;
10 2         5 my $pk = caller;
11 3     3   15 no strict 'refs';
  3         7  
  3         905  
12 2 50       12 for (@_ ? @_ : qw(get set)) {
13 4 50       30 defined &$_ or croak "$_ is not exported by $pk";
14 4         8 *{ $pk . '::' . $_ } = \&$_;
  4         2200  
15             }
16             }
17             =head1 NAME
18              
19             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              
30             =head1 SYNOPSIS
31              
32             Simply put get and set blocks at the end of your lvalue sub.
33             Please note, no comma or semicolon between statements are allowed (in case of semicolon only last statement will be take an action)
34              
35             use lvalue;
36              
37             sub mysub : lvalue {
38             get {
39             return 'result for get';
40             }
41             set {
42             my $set_value = shift;
43             # ...
44             }
45             }
46              
47             mysub() = 'test'; # will invoke set block with argument 'test';
48             print mysub(); # will invoke get block without arguments. result will be returned to print;
49              
50             sub readonly : lvalue {
51             get {
52             return 'readonly value';
53             }
54             }
55            
56             print readonly(); # ok
57             readonly = 'test'; # fails
58              
59             sub writeonly : lvalue {
60             set {
61             my $set_value = shift;
62             # ...
63             }
64             }
65            
66             writeonly = 'test'; # ok
67             print writeonly(); # fails
68              
69             =head1 EXPORT
70              
71             There are 2 export functions: C and C. If you don't want to use export, you may use full names
72              
73             sub mysub : lvalue {
74             lvalue::get {
75             return 'something';
76             }
77             lvalue::set {
78             my $set_value = shift;
79             }
80             }
81              
82             =head1 FUNCTIONS
83              
84             =head2 set
85              
86             invoked with argument from right side
87              
88             =cut
89              
90             sub set (&;@) : lvalue {
91 8     8 1 2340 my $code = shift;
92 8 100       23 if (@_) {
93 2         7 tied($_[0])->set($code);
94             }else{
95 6         36 tie $_[0], 'lvalue::tiecallback', undef, $code;
96             }
97 8         58 $_[0];
98             }
99              
100             =head2 get
101              
102             invoked without arguments. the returned value passed out
103              
104             =cut
105              
106             sub get (&;@) : lvalue {
107 8     8 1 401 my $code = shift;
108 8 100       19 if (@_) {
109 4         16 tied($_[0])->get($code);
110             }else{
111 4         17 tie $_[0], 'lvalue::tiecallback', $code, undef;
112             }
113 8         42 $_[0];
114             }
115              
116             =head1 AUTHOR
117              
118             Mons Anderson,
119              
120             =head1 BUGS
121              
122             None known
123              
124             =head1 COPYRIGHT & LICENSE
125              
126             Copyright 2009 Mons Anderson.
127              
128             This program is free software; you can redistribute it and/or modify it
129             under the same terms as Perl itself.
130              
131             =cut
132              
133             package lvalue::tiecallback;
134              
135 3     3   21 use strict;
  3         5  
  3         79  
136 3     3   2521 use Sub::Name;
  3         2310  
  3         171  
137 3     3   20 use Carp;
  3         7  
  3         1149  
138             our @CARP_NOT = 'lvalue';
139              
140             sub set {
141 2     2   5 $_[0]->[1] = $_[1];
142             }
143             sub get {
144 4     4   20 $_[0]->[0] = $_[1];
145             }
146              
147             sub TIESCALAR {
148 10     10   20 my ($pkg,$get,$set) = @_;
149 10         52 my $caller = (caller(2))[3];
150 10 100       61 subname $caller.':get',$get if $get;
151 10 100       62 subname $caller.':set',$set if $set;
152 10 50 66     51 $get or $set or croak "Neither set nor get passed";
153 10         46 return bless [$get,$set,$caller],$pkg;
154             }
155             sub FETCH {
156 5     5   69 my $self = shift;
157 5 100       129 defined $self->[0] or croak "$self->[2] is writeonly";
158 4         5 goto &{ $self->[0] };
  4         18  
159             }
160             sub STORE {
161 5     5   10 my $self = shift;
162 5 100       244 defined $self->[1] or croak "$self->[2] is readonly";
163 4         6 goto &{ $self->[1] };
  4         30  
164             }
165              
166             1;