develooper Front page | perl.perl5.porters | Postings from April 2010

what should 'local @tied' do?

Thread Next
From:
Dave Mitchell
Date:
April 11, 2010 12:18
Subject:
what should 'local @tied' do?
Message ID:
20100411191750.GE3792@iabyn.com
There are a couple of long-standing open tickets (from Michael Schwern)
to the effect that with tied arrays and hashes,
    local @tied
doesn't DWIM (RT #7938, #7939).

The current behaviour of local @tied is to create a new array, store it
in the ARRAY slot of *tied, and then I<attach tie magic to the new array
too>. This makes the local essentially a noop, and gives the following
behaviour:

    tie @ta, "Tie::StdArray";

    @a = (1,2,3); @ta = (1,2,3); print "@a | @ta\n";
    {
	local @a = (4,5,6); local @ta = (4,5,6); print "@a | @ta\n";
    }
    print "@a | @ta\n";

outputs:

    1 2 3 | 1 2 3
    4 5 6 | 4 5 6
    1 2 3 | 4 5 6  <=== expected 1 2 3 | 1 2 3

Since my work on distinguishing between container and value magic, this can
be trivially fixed, by flagging PERL_MAGIC_tied as value rather than than
container magic, and thus making the local array a new untied one. Whether
this is a good thing or not, I'm not sure about. It doesn't break anything
in the test suite, which kind of surprised me!

Anyway, I can see three possibilities for the behaviour of 'local @tied':

1. keep existing behaviour:

	{
	    local @ta
	    ...
	}

    is equivalent to

	{
	    my $saved = \@ta;
	    *ta = [];
	    tied(@ta) = tied(@$saved) # if tied() were an lvalue function
	    ...
	    *ta = $saved;
	}

    This behaviour seems particularly useless. Note that during the local
    scope the array is still tied, and on exit, nothing is restored.

2. Make the local array non-tied;

    is equivalent to

	{
	    my $saved = \@ta;
	    *ta = [];
	    ...
	    *ta = $saved;
	}

    This gives you a truly local array, and during the local scope, tied
    methods are *not* called. This latter may be good or bad depending on
    your viewpoint. Trivial to implement.

3. Keep it tied, but save all the elements:

    is equivalent to

	{
	    my @saved = ( FETCH(0), FETCH(1), ... )
	    @ta = ();
	    ...
	    @ta = ();
	    @ta = @saved
	}

    This would behave semantically similar to a non-tied array, but would
    remain tied during the local scope, which might be good or bad
    depending on your viewpoint. But potentially very costly: an array
    tied to something with lots of elements would eat up lots of time and
    memory being localised.

My preferences in descending order are 2,1,3.


-- 
The warp engines start playing up a bit, but seem to sort themselves out
after a while without any intervention from boy genius Wesley Crusher.
    -- Things That Never Happen in "Star Trek" #17

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About