Variable::Magic - Associate user-defined magic to variables from Perl.
VERSION
- Version 0.37
+ Version 0.38
SYNOPSIS
use Variable::Magic qw/wizard cast VMG_OP_INFO_NAME/;
FUNCTIONS
"wizard"
- wizard sig => ...,
- data => sub { ... },
+ wizard data => sub { ... },
get => sub { my ($ref, $data [, $op]) = @_; ... },
set => sub { my ($ref, $data [, $op]) = @_; ... },
len => sub { my ($ref, $data, $len [, $op]) = @_; ... ; return $newlen; },
signature is generated. If the signature matches an already defined
magic, then the existant magic object is returned.
+ This option is deprecated and will be removed in december 2009.
+
* "data"
A code reference to a private data constructor. It is called each
# Generate a signature
my $sig = gensig;
+ This function is deprecated and will be removed in december 2009.
+
"getsig"
getsig $wiz
# Get $wiz signature
my $sig = getsig $wiz;
+ This function is deprecated and will be removed in december 2009.
+
"cast"
- cast [$@%&*]var, [$wiz|$sig], ...
+ cast [$@%&*]var, $wiz, ...
This function associates $wiz magic to the variable supplied, without
- overwriting any other kind of magic. You can also supply the numeric
- signature $sig instead of $wiz. It returns true on success or when $wiz
- magic is already present, and croaks on error or when no magic
- corresponds to the given signature (in case a $sig was supplied). All
- extra arguments specified after $wiz are passed to the private data
- constructor in @_[1 .. @_-1]. If the variable isn't a hash, any "uvar"
- callback of the wizard is safely ignored.
+ overwriting any other kind of magic. It returns true on success or when
+ $wiz magic is already present, and croaks on error. All extra arguments
+ specified after $wiz are passed to the private data constructor in @_[1
+ .. @_-1]. If the variable isn't a hash, any "uvar" callback of the
+ wizard is safely ignored.
# Casts $wiz onto $x, and pass '1' to the data constructor.
my $x;
If you want to overcome the possible deletion of the 'TZ' entry, you
have no choice but to rely on "store" uvar magic.
- "cast" can be called from any magical callback, and in particular from
- "data". This allows you to recursively cast magic on datastructures :
-
- my $wiz;
- $wiz = wizard
- data => sub {
- my ($var, $depth) = @_;
- $depth ||= 0;
- my $r = ref $var;
- if ($r eq 'ARRAY') {
- &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for @$var;
- } elsif ($r eq 'HASH') {
- &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for values %$var;
- }
- return $depth;
- },
- free => sub {
- my ($var, $depth) = @_;
- my $r = ref $var;
- print "free $r at depth $depth\n";
- ();
- };
-
- {
- my %h = (
- a => [ 1, 2 ],
- b => { c => 3 }
- );
- cast %h, $wiz;
- }
-
- When %h goes out of scope, this will print something among the lines of
- :
-
- free HASH at depth 0
- free HASH at depth 1
- free SCALAR at depth 2
- free ARRAY at depth 1
- free SCALAR at depth 3
- free SCALAR at depth 3
-
- Of course, this example does nothing with the values that are added
- after the "cast".
-
"getdata"
- getdata [$@%&*]var, [$wiz|$sig]
+ getdata [$@%&*]var, $wiz
- This accessor fetches the private data associated with the magic $wiz
- (or the signature $sig) in the variable. It croaks when $wiz or $sig do
- not represent a valid magic object, and returns an empty list if no such
- magic is attached to the variable or when the wizard has no data
- constructor.
+ This accessor fetches the private data associated with the magic $wiz in
+ the variable. It croaks when $wiz do not represent a valid magic object,
+ and returns an empty list if no such magic is attached to the variable
+ or when the wizard has no data constructor.
# Get the attached data, or undef if the wizard does not attach any.
my $data = getdata $x, $wiz;
"dispell"
- dispell [$@%&*]variable, [$wiz|$sig]
+ dispell [$@%&*]variable, $wiz
The exact opposite of "cast" : it dissociates $wiz magic from the
- variable. You can also pass the magic signature $sig as the second
- argument. This function returns true on success, 0 when no magic
- represented by $wiz or $sig could be found in the variable, and croaks
- if the supplied wizard or signature is invalid.
+ variable. This function returns true on success, 0 when no magic
+ represented by $wiz could be found in the variable, and croaks if the
+ supplied wizard is invalid.
# Dispell now.
die 'no such magic in $x' unless dispell $x, $wiz;
"SIG_MIN"
The minimum integer used as a signature for user-defined magic.
+ This constant is deprecated and will be removed in december 2009.
+
"SIG_MAX"
The maximum integer used as a signature for user-defined magic.
+ This constant is deprecated and will be removed in december 2009.
+
"SIG_NBR"
SIG_NBR = SIG_MAX - SIG_MIN + 1
+ This constant is deprecated and will be removed in december 2009.
+
"MGf_COPY"
Evaluates to true iff the 'copy' magic is available.
"VMG_COMPAT_ARRAY_PUSH_NOLEN"
True for perls that don't call 'len' magic when you push an element in a
- magical array.
+ magical array. Starting from perl 5.11.0, this only refers to pushes in
+ non-void context and hence is false.
+
+ "VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID"
+ True for perls that don't call 'len' magic when you push in void context
+ an element in a magical array.
"VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID"
True for perls that don't call 'len' magic when you unshift in void
Value to pass with "op_info" to get a "B::OP" object representing the
current op in the magic callbacks.
+COOKBOOK
+ Associate an object to any perl variable
+ This can be useful for passing user data through limited APIs.
+
+ {
+ package Magical::UserData;
+
+ use Variable::Magic qw/wizard cast getdata/;
+
+ my $wiz = wizard data => sub { \$_[1] };
+
+ sub ud (\[$@%*&]) : lvalue {
+ my ($var) = @_;
+ my $data = &getdata($var, $wiz);
+ unless (defined $data) {
+ &cast($var, $wiz);
+ $data = &getdata($var, $wiz);
+ die "Couldn't cast UserData magic onto the variable" unless defined $data;
+ }
+ $$data;
+ }
+ }
+
+ {
+ BEGIN { *ud = \&Magical::UserData::ud }
+
+ my $cb;
+ $cb = sub { print 'Hello, ', ud(&$cb), "!\n" };
+
+ ud(&$cb) = 'world';
+ $cb->(); # Hello, world!
+ }
+
+ Recursively cast magic on datastructures
+ "cast" can be called from any magical callback, and in particular from
+ "data". This allows you to recursively cast magic on datastructures :
+
+ my $wiz;
+ $wiz = wizard data => sub {
+ my ($var, $depth) = @_;
+ $depth ||= 0;
+ my $r = ref $var;
+ if ($r eq 'ARRAY') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for @$var;
+ } elsif ($r eq 'HASH') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for values %$var;
+ }
+ return $depth;
+ },
+ free => sub {
+ my ($var, $depth) = @_;
+ my $r = ref $var;
+ print "free $r at depth $depth\n";
+ ();
+ };
+
+ {
+ my %h = (
+ a => [ 1, 2 ],
+ b => { c => 3 }
+ );
+ cast %h, $wiz;
+ }
+
+ When %h goes out of scope, this will print something among the lines of
+ :
+
+ free HASH at depth 0
+ free HASH at depth 1
+ free SCALAR at depth 2
+ free ARRAY at depth 1
+ free SCALAR at depth 3
+ free SCALAR at depth 3
+
+ Of course, this example does nothing with the values that are added
+ after the "cast".
+
PERL MAGIC HISTORY
The places where magic is invoked have changed a bit through perl
history. Here's a little list of the most recent ones.
an element into a magical array in void context. The "push" part was
already covered by *p25854*.
+ *g9cdcb38b* : 'len' magic is called again when pushing into a
+ magical array in non-void context.
+
EXPORT
The functions "wizard", "gensig", "getsig", "cast", "getdata" and
"dispell" are only exported on request. All of them are exported by the