X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;ds=sidebyside;f=lib%2FVariable%2FMagic.pm;h=3668432486cffb61f6e90ebfcf3a0700f8311dea;hb=d33407fbe0b4c8c80751c26f5d8ec3622c26e54a;hp=19ba55f68748ffaadf2620854187de321e629f15;hpb=8d1e537ed209474d537750620e118f79455a883f;p=perl%2Fmodules%2FVariable-Magic.git
diff --git a/lib/Variable/Magic.pm b/lib/Variable/Magic.pm
index 19ba55f..3668432 100644
--- a/lib/Variable/Magic.pm
+++ b/lib/Variable/Magic.pm
@@ -1,63 +1,101 @@
package Variable::Magic;
-use 5.007003;
+use 5.008;
use strict;
use warnings;
-use Carp qw/croak/;
-
=head1 NAME
Variable::Magic - Associate user-defined magic to variables from Perl.
=head1 VERSION
-Version 0.28
+Version 0.46
=cut
our $VERSION;
BEGIN {
- $VERSION = '0.28';
+ $VERSION = '0.46';
}
=head1 SYNOPSIS
- use Variable::Magic qw/wizard cast dispell/;
-
- my $wiz = wizard set => sub { print STDERR "now set to ${$_[0]}!\n" };
- my $a = 1;
- cast $a, $wiz;
- $a = 2; # "now set to 2!"
- dispell $a, $wiz;
- $a = 3 # (nothing)
+ use Variable::Magic qw;
+
+ { # A variable tracer
+ my $wiz = wizard(
+ set => sub { print "now set to ${$_[0]}!\n" },
+ free => sub { print "destroyed!\n" },
+ );
+
+ my $a = 1;
+ cast $a, $wiz;
+ $a = 2; # "now set to 2!"
+ } # "destroyed!"
+
+ { # A hash with a default value
+ my $wiz = wizard(
+ data => sub { $_[1] },
+ fetch => sub { $_[2] = $_[1] unless exists $_[0]->{$_[2]}; () },
+ store => sub { print "key $_[2] stored in $_[-1]\n" },
+ copy_key => 1,
+ op_info => VMG_OP_INFO_NAME,
+ );
+
+ my %h = (_default => 0, apple => 2);
+ cast %h, $wiz, '_default';
+ print $h{banana}, "\n"; # "0" (there is no 'banana' key in %h)
+ $h{pear} = 1; # "key pear stored in helem"
+ }
=head1 DESCRIPTION
-Magic is Perl way of enhancing objects.
-This mechanism let the user add extra data to any variable and hook syntaxical operations (such as access, assignation or destruction) that can be applied to it.
-With this module, you can add your own magic to any variable without the pain of the C API.
+Magic is Perl's way of enhancing variables.
+This mechanism lets the user add extra data to any variable and hook syntactical operations (such as access, assignment or destruction) that can be applied to it.
+With this module, you can add your own magic to any variable without having to write a single line of XS.
-Magic differs from tieing and overloading in several ways :
+You'll realize that these magic variables look a lot like tied variables.
+It's not surprising, as tied variables are implemented as a special kind of magic, just like any 'irregular' Perl variable : scalars like C<$!>, C<$(> or C<$^W>, the C<%ENV> and C<%SIG> hashes, the C<@ISA> array, C and C lvalues, L variables...
+They all share the same underlying C API, and this module gives you direct access to it.
+
+Still, the magic made available by this module differs from tieing and overloading in several ways :
=over 4
=item *
-Magic isn't copied on assignation (as for blessed references) : you attach it to variables, not values.
+It isn't copied on assignment.
+
+You attach it to variables, not values (as for blessed references).
=item *
-It doesn't replace the original semantics : magic callbacks trigger before the original action take place, and can't prevent it to happen.
+It doesn't replace the original semantics.
+
+Magic callbacks usually get triggered before the original action takes place, and can't prevent it from happening.
+This also makes catching individual events easier than with C, where you have to provide fallbacks methods for all actions by usually inheriting from the correct C class and overriding individual methods in your own class.
=item *
-It's mostly invisible at the Perl level : magical and non-magical variables cannot be distinguished with C[, C or another trick.
+It's type-agnostic.
+
+The same magic can be applied on scalars, arrays, hashes, subs or globs.
+But the same hook (see below for a list) may trigger differently depending on the the type of the variable.
=item *
-It's notably faster, since perl's way of handling magic is lighter by nature, and there's no need for any method resolution.
+It's mostly invisible at the Perl level.
+
+Magical and non-magical variables cannot be distinguished with C][, C or another trick.
+
+=item *
+
+It's notably faster.
+
+Mainly because perl's way of handling magic is lighter by nature, and because there's no need for any method resolution.
+Also, since you don't have to reimplement all the variable semantics, you only pay for what you actually use.
=back
@@ -69,20 +107,22 @@ The operations that can be overloaded are :
C
-This magic is invoked when the variable is evaluated (does not include array/hash subscripts and slices).
+This magic is invoked when the variable is evaluated.
+It is never called for arrays and hashes.
=item *
C
-This one is triggered each time the value of the variable changes (includes array/hash subscripts and slices).
+This one is triggered each time the value of the variable changes.
+It is called for array subscripts and slices, but never for hashes.
=item *
C
This magic is a little special : it is called when the 'size' or the 'length' of the variable has to be known by Perl.
-Typically, it's the magic involved when an array is evaluated in scalar context, but also on array assignation and loops (C, C], L, L and L are only exported on request.
All of them are exported by the tags C<':funcs'> and C<':all'>.
-The constants L, L, L, L, L, L and L are also only exported on request.
-They are all exported by the tags C<':consts'> and C<':all'>.
+All the constants are also only exported on request, either individually or by the tags C<':consts'> and C<':all'>.
=cut
-use base qw/Exporter/;
+use base qw;
our @EXPORT = ();
our %EXPORT_TAGS = (
- 'funcs' => [ qw/wizard gensig getsig cast getdata dispell/ ],
- 'consts' => [ qw/SIG_MIN SIG_MAX SIG_NBR MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR/,
- qw/VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID VMG_COMPAT_ARRAY_UNDEF_CLEAR/,
- qw/VMG_COMPAT_SCALAR_LENGTH_NOLEN/,
- qw/VMG_PERL_PATCHLEVEL/,
- qw/VMG_THREADSAFE/ ]
+ 'funcs' => [ qw ],
+ 'consts' => [ qw<
+ MGf_COPY MGf_DUP MGf_LOCAL VMG_UVAR
+ VMG_COMPAT_ARRAY_PUSH_NOLEN VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID
+ VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID
+ VMG_COMPAT_ARRAY_UNDEF_CLEAR
+ VMG_COMPAT_SCALAR_LENGTH_NOLEN
+ VMG_COMPAT_GLOB_GET
+ VMG_PERL_PATCHLEVEL
+ VMG_THREADSAFE VMG_FORKSAFE
+ VMG_OP_INFO_NAME VMG_OP_INFO_OBJECT
+ > ],
);
our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS;
$EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
=head1 CAVEATS
-If you store a magic object in the private data slot, the magic won't be accessible by L since it's not copied by assignation.
+If you store a magic object in the private data slot, the magic won't be accessible by L since it's not copied by assignment.
The only way to address this would be to return a reference.
If you define a wizard with a C callback and cast it on itself, this destructor won't be called because the wizard will be destroyed first.
+In order to define magic on hash members, you need at least L 5.10.0 (see L)
+
=head1 DEPENDENCIES
-L 5.7.3.
+L 5.8.
+
+A C compiler.
+This module may happen to build with a C++ compiler as well, but don't rely on it, as no guarantee is made in this regard.
L (standard since perl 5), L (standard since perl 5.006).
@@ -502,7 +657,7 @@ Tests code coverage report is available at L