Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: Allocation of anonymous arrays

by Athanasius (Archbishop)
on Feb 07, 2014 at 09:46 UTC ( [id://1073846]=note: print w/replies, xml ) Need Help??


in reply to Allocation of anonymous arrays

Hello OwlHoot, and welcome to the Monastery!

Consider:

my @foo = (42, 43, 45); my @bar = (42, 43, 45);

Would Perl see that both arrays contain the same values, and therefore “optimise” the storage by having @foo and @bar refer to the same set of storage locations? No, because these arrays must be allowed to change independently. For example, incrementing $foo[0] should have no impact on the value of $bar[0].

Now, an anonymous array is just an array which is accessed by a reference rather than a name. Two anonymous arrays which happen to share the same data cannot be optimised to refer to common storage, because either is free to change independently of the other as the script runs.

So, I think your colleague is correct. But — please explain the motivation for using array references as hash keys in this way?!?

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Allocation of anonymous arrays
by OwlHoot (Novice) on Feb 07, 2014 at 11:19 UTC

    Thanks for reply Athanasius (and to everyone who has replied so promptly)

    With reference to your first example, in theory I would have thought perl (or "a Similar Language") could indeed have @foo and @bar refer to the same storage initially. Then as soon as any code wanted to amend one of them, or even define a reference to them, perl could create a copy and start using that.

    (Granted this probably wouldn't be a good idea in practice because most arrays defined explicitly will usually be amended, or references to them defined, during the subsequent running of the program.)

    Literal array references not initially assigned to a variable seem even more suitable for this "copy on write" treatment, as they are initially and quite likely never amended or pointed to explicitly. But I can see that in principle one could have something like:

    my %fred = ( [1, 2, 3] = [1, 1, 0], [3, 4, 2] = [1, 0, 1], [2, 2, 1] = [1, 1, 0], ); my $i = 0; foreach my $ref (keys %fred) ( $ref->[2] = ++$i; )

    So I'm still not entirely convinced one way or the other!

    As for why my colleague chose this system, it is a test script in which each key array represents a test case in compact form and the value represents outcome flags. (I would have represented these in a rather different way, all in one array for example, but each to their own.)

    Regards

    John R Ramsden

      So I'm still not entirely convinced one way or the other!

      Sorry guys (you and your colleague), you are arguing about silly things. Of course, your colleague is right. Perl will never optimize away arrays with the same content. It is just silly for perl to run through all arrays trying to see if they have the same content. But your colleague is completely wrong using array references as keys.

      Have you actually tried to run the code you gave above? If you run it with "use strict;" then you'll get error "Can't use string ("ARRAY(0xc80de8)") as an ARRAY ref while "strict refs" in use". This is because array that you have given when you created hash is already gone, so perl would try to create new NAMED array and the name for that array would be ARRAY(0xc80de8) or whatever is the unique string that has identified original array.

      ... perl ... could indeed have @foo and @bar refer to the same storage initially. Then as soon as any code wanted to amend one of them, or even define a reference to them, perl could create a copy and start using that.

      (Granted this probably wouldn't be a good idea ...)

      You're right: Perl could do that, and it's a bad idea, and so Perl doesn't do that.

      ... each key array represents a test case in compact form ...

      The representational form is compact, indeed: it is the nullity; it has ceased to be; bereft of life, it rests in peace. As soon as the anonymous array constructor  [ ... ] finishes its job, the reference it returns is immediately converted into a string and ceases to exist as a reference. Because the referent can no longer be accessed in any way whatsoever (because it has no reference), it is marked for garbage collection (its reference count is zero) and, in the fullness of time, it softly and silently vanishes away.

      Oops, I meant:
      foreach my $ref (keys %fred) ( $fred{$ref}->[2] = ++$i; )
        sure, but you can write  for my $ref ( values %fred ){ $ref->[2] = ++$i; } so that $ref is an actual ref :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1073846]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-03-29 12:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found