package deferred_interpolation; use strict; # $Id: deferred_interpolation.pm,v 1.1 2000/09/21 07:19:30 abigail Exp abigail $ # # Using this pragma means that if you have a string using scalar # interpolation, the interpolation is done when the string is *used*, # not when the string is actually defined. # # This will not work with array interpolation. # # To achieve this result, strings will be overloaded, using # overload::constant. Strings will be represented as a blessed reference # to an array, where the array contains *references* to the various # string components. Since Perl passes implicite references as arguments # to functions if it can, this just works out. The reference is blessed # into a package that overloads concatenation and stringify. # # $Log: deferred_interpolation.pm,v $ # Revision 1.1 2000/09/21 07:19:30 abigail # Initial revision # use vars qw /$VERSION/; ($VERSION) = '$Revision: ' =~ /([\d.]+)/; use overload '.' => sub { # We can concatenate with pieces that are normal Perl strings, for # instance from single quoted strings. However, overloading single # quoted constants won't do, as for instance "foo@array" is just # a short hand for "foo" . join $" => @array. $_ [0] = [\$_ [0]] unless ref $_ [0]; $_ [1] = [\$_ [1]] unless ref $_ [1]; # At this point, both $_ [0] and $_ [1] are references to arrays # containing string pieces. It's simple to listify both of them, # and return an appropriate blessed reference to an array containing # both lists. However, this sub might be called with the arguments in # the "wrong" order; if so, $_ [2] is true. Hence, the inner voodoo. # Note that @_ [0, 1] = @_ [1, 0] if $_ [2] will not work. bless [map {@{$_ [$_ [2] ? 1 - $_ : $_]}} 0 => 1] => __PACKAGE__ }; use overload '""' => sub { # Dereference the pieces, and join them with nothing in between. join "" => map {$$_} @{$_ [0]} }; sub import { # We only need to perform magic on double quoted strings, not # on single quoted strings, or tr///. # There isn't much point in overloading the RHS of s///, as that # will reinterpolate anyway, unless you tell Perl not to. overload::constant q => sub { $_ [2] eq "qq" ? bless [\$_ [1]] => __PACKAGE__ : $_ [1] } } sub unimport { overload::remove_constant q => 0; } 1; __END__ =pod =head1 NAME deferred_interpolation -- Delay interpolation of scalar till string is used. =head1 SYNOPSIS use deferred_interpolation; my $name; my $str = "My name is $name."; $name = "Abigail"; print $str; # My name is Abigail. $name = "Larry Wall"; print $str; # My name is Larry Wall. no deferred_interpolation; $name = "Edsger W. Dijkstra"; my $str2 = "My name is not $name."; $name = "Donald E. Knuth"; print $str2; # My name is not Edsger W. Dijkstra. =head1 DESCRIPTION Normally, Perl performs interpolation when a string is defined. But sometimes it would be convenient to perform the interpolation when the string is actually used, interpolating the current value of the variables. This package will do that, but for interpolation of scalar variables only. Arrays are interpolated when the string is defined. =head1 BUGS The following cases do not work; they will put something of the form C<ARRAY(0x815bc88)> in your string. =over 4 =item o my $name; my $str = "My name is $name."; foreach $name ("Abigail", "Larry Wall") { print $str } =item o my $count = 5; my $str = "I have ${\($count * 10)} marbles.\n"; print $str; Use my $str = "I have @{[$count * 10]} marbles.\n"; instead. (This of course will be interpolated at when the string is defined, not when it is used). =item o The name of the package is way too long. =back =head1 HISTORY $Log: deferred_interpolation.pm,v $ Revision 1.1 2000/09/21 07:19:30 abigail Initial revision =head1 THANKS The author wishes to thank Dave Sherohman, who posted a question that lead to this package I<news:slrn8sib1o.npj.esper@pchan.dojo>, and Damian Conway for his talk about Object Orientism at YAPC 19100; without it, the author would never have heard of overloaded constants. =head1 AUTHOR This package is written by Abigail, I<abigail@foad.org>. =head1 COPYRIGHT and LICENSE This program is copyright 2000 by Abigail. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut ==== Want to unsubscribe from Fun With Perl? Well, if you insist... ==== Send email to <fwp-request@technofile.org> with message _body_ ==== unsubscribe