File Coverage

blib/lib/String/Defer.pm
Criterion Covered Total %
statement 40 40 100.0
branch 15 18 83.3
condition 9 12 75.0
subroutine 13 13 100.0
pod 5 5 100.0
total 82 88 93.1


line stmt bran cond sub pod time code
1             package String::Defer;
2              
3 6     6   53422 use warnings;
  6         15  
  6         196  
4 6     6   31 use strict;
  6         9  
  6         208  
5 6     6   38 no warnings "uninitialized"; # SHUT UP
  6         13  
  6         614  
6              
7             our $VERSION = "3";
8              
9             =head1 NAME
10              
11             String::Defer - Strings with deferred interpolation
12              
13             =head1 SYNOPSIS
14              
15             my $defer = String::Defer->new(\my $targ);
16             my $str = "foo $defer bar";
17              
18             $targ = "one"; say $str; # foo one bar
19             $targ = "two; say $str; # foo two bar
20              
21             =head1 DESCRIPTION
22              
23             C objects provide delayed interpolation. They have concat
24             (C) overloading, which means that an interpolation like
25              
26             "foo $defer bar"
27              
28             will itself produce a C object, and the stringification
29             of C<$defer> will be delayed until I object is stringified.
30              
31             =cut
32              
33             use overload (
34 6         48 q/""/ => "force",
35             q/./ => "concat",
36             fallback => 1, # Why is this not the default?
37 6     6   8506 );
  6         5674  
38 6     6   777 use Exporter "import";
  6         12  
  6         447  
39             our @EXPORT_OK = qw/djoin/;
40              
41 6     6   41 use Carp;
  6         10  
  6         861  
42 6     6   36 use Scalar::Util qw/reftype blessed/;
  6         17  
  6         5359  
43              
44             =head1 METHODS
45              
46             =head2 C<< String::Defer->new(\$scalar | \&code) >>
47              
48             This is the usual constructor (though C and C can also be
49             seen as constructors). The argument is either a scalar ref or a code
50             ref, unblessed, and specifies a piece of the string that should be lazily
51             evaluated. When C is called, a scalar ref will be dereferenced
52             and the referent stringified; a code ref will be called with no
53             arguments.
54              
55             It currently isn't possible to pass an object with C<${}> or C<&{}>
56             overloading; see L below. If you wish to defer stringification of
57             an object with stringify overloading, you need to pass a B to
58             (your existing reference to) the object, like this:
59              
60             my $obj = Some::Class->new(...);
61             my $defer = String::Defer->new(\$obj);
62              
63             It currently B possible to pass a ref to a scalar which happens to
64             be holding a bare glob, like this:
65              
66             my $targ = *FOO;
67             my $defer = String::Defer->new(\$targ);
68              
69             but that may not be the case in the future. I'd like, at some point, to
70             support passing a globref as a filehandle, and I'm not sure it's
71             possible to distinguish between 'a ref to a scalar variable which
72             happens to be currently holding a glob' and 'a ref to a real glob'.
73              
74             It is also possible to pass a ref to a substring of another string,
75             like this:
76              
77             my $targ = "one two three";
78             my $defer = String::Defer->new(\substr $targ, 4, 3);
79              
80             say $defer; # two
81             $targ = uc $targ; say $defer; # TWO
82              
83             The C will track that substring of the target string as
84             it changes. Before perl 5.16, the target string must be long enough at
85             the time the reference is created for this to work correctly; this has
86             been fixed in the development version of perl, which will be released as
87             5.16.
88              
89             =cut
90              
91             # This list is a little bizarre, but so is the list of things
92             # that can legitimately be stuffed into a scalar variable. If
93             # BIND ever sees the light of day this will need revisiting.
94             my %reftypes = map +($_, 1), (
95             "CODE", # ->new(sub { })
96             "SCALAR", # my $x; ->new(\$x)
97             "VSTRING", # my $x = v1; ->new(\$x)
98             "REF", # my $x = \1; ->new(\$x)
99             "REGEXP", # my $x = ${qr/x/}; ->new(\$x)
100              
101             # This should be considered experimental. It may be more beneficial
102             # to treat a globref as a filehandle. I don't know if there's any
103             # way to distinguish between my $x = *STDIN; \$x
104             # and either of \*STDIN
105             # open my $x, ...; $x
106             # SvFAKE on the glob seems to be the key, here, but I don't know if
107             # that's visible from Perl. (...of course it is, that's what B's
108             # there for.)
109             "GLOB", # my $x = *STDIN; ->new(\$x)
110             "LVALUE", # my $x = "foo"; ->new(\substr($x, 0, 2))
111             # This will track that substring of the variable as it
112             # changes, which is pretty nifty.
113             );
114              
115             sub new {
116 238     238 1 302955 my ($class, $val) = @_;
117             # XXX What about objects with ${}/&{} overload? Objects pretending
118             # to be strings can be passed by (double) ref, and will be allowed
119             # by the REF entry, but not objects pretending to be references.
120 238 100 66     3978 ref $val and not blessed $val and $reftypes{reftype $val}
    100 100        
121             or croak "I need a SCALAR or CODE ref, not " .
122             (blessed $val ? "an object" : reftype $val);
123 228         2437 bless [$val], $class;
124             }
125              
126             =head2 C<< $defer->concat($str, $reverse) >>
127              
128             Concatentate C<$str> onto C<$defer>, and return a new C
129             containing the result. This is the method which implements the C
130             overloading.
131              
132             Passing another C will B force the object out to a
133             plain string. Passing any other object with string overload, however,
134             B. If you want to defer the stringification, wrap it in a
135             C.
136              
137             =cut
138              
139             # This will force a stringify now, which is what happens with a
140             # normal concat. I don't think allowing other random stringifyable
141             # objects to be deferred (when the user hasn't explicitly asked for it)
142             # is going to be helpful.
143 571 100   571   833 sub _expand { eval { $_[0]->isa(__PACKAGE__) } ? @{$_[0]} : "$_[0]" }
  571         13566  
  135         1653  
144              
145             sub concat {
146 328     328 1 100324 my ($self, $str, $reverse) = @_;
147             # { local $" = "|"; no overloading;
148             # carp "CONCAT: [@$self] [$str] $reverse";
149             # }
150 328 50       1318 my $class = Scalar::Util::blessed $self
151             or croak "String::Defer->concat is an object method";
152              
153 328         1244 my @str = _expand $str;
154 328 100 66     7238 bless [
155             grep ref || length,
156             ($reverse ? (@str, @$self) : (@$self, @str))
157             ], $class;
158             }
159              
160             =head2 C<< $defer->force >>
161              
162             Stringify the object, including all its constituent pieces, and return
163             the result as a plain string. This implements the C overload.
164              
165             Note that while this returns a plain string, it leaves the object itself
166             unaffected. You can C<< ->force >> it again later, and potentially get a
167             different result.
168              
169             =cut
170              
171             sub force {
172 345     345 1 354661 my ($self) = @_;
173             # { local $" = "|"; no overloading;
174             # carp "FORCE: [@$self]";
175             # }
176 345 100       8117 join "", map +(
    100          
177             ref $_
178             # Any objects should have been rejected or stringified by
179             # this point (but see XXX above)
180             ? reftype $_ eq "CODE"
181             ? $_->()
182             : $$_
183             : $_
184             ), @$self;
185             }
186              
187             =head2 C<< String::Defer->join($with, @strs) >>
188              
189             Join strings without forcing, and return a deferred result.
190              
191             Arguments are as for L|perlfunc/join>, but while the
192             builtin will stringify immediately and return a plain string, this will
193             allow any of C<$with> or C<@strs> to be deferred, and will carry the
194             deferral through to the result.
195              
196             Note that this is, in fact, a constructor: it must be called as a class
197             method, and the result will be in that class. (But see L.)
198              
199             =cut
200              
201             # Join without forcing. The other string ops might be useful, and could
202             # certainly be implemented with closures, but would be substantially
203             # more complicated.
204             sub join {
205 69     69 1 36949 my ($class, $with, @strs) = @_;
206              
207             # This is a class method (a constructor, in fact), to allow
208             # subclasses later, but the implementation may need adjusting. I
209             # probably shouldn't be poking in the objects' guts directly, and
210             # using a ->pieces method or something instead.
211             # OTOH, @{} => "pieces" would Just Work...
212 69 50       341 ref $class and croak "String::Defer->join is a class method";
213              
214             # { local $" = "|"; no overloading;
215             # carp "JOIN: [$with] [@strs] -> [$class]";
216             # }
217              
218             # This could be optimised, but stick with the simple implementation
219             # for now.
220 69         144 my @with = _expand $with;
221 69 50       300 my @last = @strs ? _expand(pop @strs) : ();
222 105         1048 bless [
223             grep ref || length,
224 69   66     218 (map { (_expand($_), @with) } @strs),
225             @last,
226             ], $class;
227             }
228              
229             =head2 C<< djoin $with, @strs >>
230              
231             This is a shortcut for C<< String::Defer->join >> as an exportable
232             function. Obviously this won't be any use if you're subclassing.
233              
234             =cut
235              
236             # Utility sub since Cjoin()> is rather a mouthful. This
237             # always creates a String::Defer, rather than a subclass.
238 23     23 1 21218 sub djoin { __PACKAGE__->join(@_) }
239              
240             =head1 BUGS
241              
242             Please report any bugs to .
243              
244             =head2 Bugs in perl
245              
246             =head3 Assignment to an existing lexical
247              
248             Under some circumstances an assignment like
249              
250             my $defer = String::Defer->new(\my $targ);
251             my $x;
252             $x = "A $defer B";
253              
254             will leave C<$x> holding a plain string rather than a C,
255             because perl calls stringify overloading earlier than it needed to. This
256             happens if (and only if)
257              
258             =over 4
259              
260             =item -
261              
262             a double-quoted string (with an interpolated C) is assigned
263             to a lexical scalar;
264              
265             =item -
266              
267             that lexical has already been declared;
268              
269             =item -
270              
271             no other operators intervene between the interpolation and the
272             assignment;
273              
274             =item -
275              
276             the interpolation has at least three pieces (so, two constant sections
277             with a variable between them, or vice versa, or more pieces than that).
278              
279             =back
280              
281             So the following are all OK:
282              
283             my $x = "A $defer B"; # newly declared lexical
284             my %h;
285             $h{x} = "A $defer B"; # hash element, not lexical scalar
286             $x = "A $defer"; # only two pieces
287             $x = "" . "A $defer B"; # intervening operator
288              
289             The simplest workaround is to turn at least one section of the
290             interpolation into an explicit concatenation, or even just to
291             concatenate an empty string as in the last example above.
292              
293             This applies to C as well as to C variables, but not to
294             C globals, despite their partially lexical scope.
295              
296             =head3 C<++> and C<-->
297              
298             The increment and decrement operators don't appear to honour the
299             stringify overloading, and instead operate on the numerical refaddr of
300             the object. Working aroung this in this module is a little tricky, since
301             the calling convention of the C<++> and C<--> overloads assume you want
302             the object to stay an object, whereas what we want here is a plain
303             string. C<+=> and C<-=> work correctly, and B leave you with a plain
304             string.
305              
306             =head3 Tied scalars
307              
308             Before perl 5.14, tied scalars don't always honour overloading properly.
309             A tied scalar whose C returns a C will instead
310             appear to contain a plain string at least the first time it is
311             evaluated. As of 5.14, this has been fixed.
312              
313             =head2 Subclassing
314              
315             Subclassing is currently rather fragile. The implementation assumes the
316             object is implemented as an array of pieces, where those pieces are
317             either plain strings, scalar refs, or code refs, but I would like to
318             change this to something like a C<< ->pieces >> method. While it ought
319             to be possible to override C<< ->force >> to create an object which
320             builds the final string differently, it's not very clear how to best
321             handle cases like an object of one subclass being concatenated with an
322             object of another.
323              
324             =head2 C and C; other string ops
325              
326             The repeat ops C and C currently force deferred strings. It would
327             be better if they produced deferred results, and better still if they
328             could do so without duplicating the contents of the internal array.
329             (Allowing the RHS to be deferred as well might be a nice touch.)
330              
331             Much the same applies to all the other string ops. While functions like
332             C and C can't be overloaded, they can be provided as
333             class methods. I suspect the best way forward here will be to provide a
334             set of subclasses of C, each of which knows how to
335             implement one string operation. This would mean that C<< ->join >> would
336             no longer return a C, but rather a C
337             with internal references to its constituent pieces.
338              
339             =head2 Objects pretending to be refs
340              
341             Objects with C<${}> and C<&{}> overloads ought to be accepted as
342             stand-ins for scalar and code refs, but currently they aren't. In part
343             this is because I'm not sure which to give precedece to if an object
344             implements both.
345              
346             =head2 Efficiency
347              
348             The implementation of both C and C is rather simple, and
349             makes no attempt to merge adjacent constant strings. Join, in
350             particular, will return a deferred string even if passed all plain
351             strings, which should really be fixed.
352              
353             =head1 AUTHOR
354              
355             Ben Morrow
356              
357             =head1 COPYRIGHT
358              
359             Copyright 2011 Ben Morrow .
360              
361             Released under the BSD licence.
362              
363             =head1 SEE ALSO
364              
365             L for a more generic but more intrusive deferral
366             mechanism.
367              
368             =cut
369              
370             1;
371