I've created a module Magic::Attach. It allows you to attach one referant to another.

The purpose of which is to allow a sub or any other type of object to attach some private data to a reference. This could be for lazy evaluation of arguments or whatever purpose you can think of.

When you attach a ref to another ref, you can optionally specify a nameid to avoid collisions. Multiple attachments are fine but other modules that implemented their own magic using the '~' user extension type may clobber us if they are less careful.

The module can be found here

This is my first real forray into XS so I'm sure there are things that could be done better. Comments and criticisms welcome.
It works with 5.6.1 and above (possibly with earlier versions but I haven't confirmed this.) The naming of the routines may change. (Would bind/bound/unbind be better suited?)

My other thought is if this is a generally useful module, perhaps the "optional nameid" shouldn't be optional (Currently it defaults to Magic::Attach). I worry that if this finds use and the default nameid are used in two different places it will lead to very, very subtle bugs. I can't speak for anyone else but before embarking on this, I would never think to look at "magic vtables" for problems.

I'd really appreciate any feedback on the implementation, usefulness, etc of this.

$attached = attach_var($target_ref, $attach, [$optional_name]); $attached = attached($target_ref, [ $optional_name ]); $attached = unattach_var($target_ref, [ $optional_name ]); # A few trivial examples. sub elements(\@$){ my ($ref,$size) = @_; $size = 1 unless $size; my $info = attached($ref,'elements') || attach_var($ref,[0,$size], +'elements'); my @ret = (); if( $info->[0] >= @$ref ) { unattach_var($ref,'elements'); return; }else{ @ret = @{$ref}[$info->[0]..($info->[0]+$info->[1] -1)]; $info->[0]+= $info->[1]; } @ret; } while( my @els = elements(@large_array,4) ){ # Process non destructively } # Lazily generate a span of integers. sub int_span($$){ my $info = attached(\$_[0],'INT_SPAN') || attach_var(\$_[0],[$_[0] +,$_[1] ],'INT_SPAN'); unattach_var(\$_[0],'INT_SPAN') and return if $info->[0] > $info +->[1]; return $info->[0]++; } while(my $i = int_span(1,1000000000)){ print $i,"\n"; }
Thanks,
-Lee

"To be civilized is to deny one's nature."
update
The "magic" refered to is internal to the perl interpreter. See "Magic Variables" in perlguts for more information.
update Jan 21 one more example.
# Persistant subroutine data sub somesub { my $p_args = attached(\&somesub,'somesub') || attach_var(\&somesub +,{called=>0},'somesub'); ++$p_args->{called}; # The persistant arg hash could be keyed on the caller info if des +ired # for context sensitivity }

In reply to RFC Magic::Attach by shotgunefx

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.