Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Update references

by Anonymous Monk
on May 13, 2012 at 14:30 UTC ( #970288=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I'd like to have a reference to an array element (or hash element) which is updated as the original array is changed. See code below:
print "--------Trying with arrays-------\n"; my @a = (0, 1, 2, 3); my $ar = \@a; # Array reference my $air = \$a[0]; # Reference to member of an array print "Define array >@a<\nCreate a reference to \$a[0]\n"; print "array ref: >@$ar< \n"; print "array index ref: >$$air<\n"; @a = ('a','b','c'); print "Change array to >@a<\n"; print "array ref: >@$ar< \n"; print "array index ref: >$$air<\n"; # <--- I'd like to get "a" here print "--------Trying with strings-------\n"; my $s = "string"; my $sr = \$s; print "orignal: >$s<\n"; print "reference: >$$sr<\n"; $s = "changed string"; print "string: >$s<\n"; print "string reference: >$$sr<\n";
OUPUT:
--------Trying with arrays------- Define array >0 1 2 3< Create a reference to $a[0] array ref: >0 1 2 3< array index ref: >0< Change array to >a b c< array ref: >a b c< array index ref: >0< --------Trying with strings------- orignal: >string< reference: >string< string: >changed string< string reference: >changed string<

It works with the string, but it doesn't work with the array element. I'd like to get the updated array element when dereferencing. This example is simplified. The original problem is a referenced variable for a Tk Checkbutton where the referent get's updated by another subroutine, but the reference still shows the old value. I don't want to update the data through the reference as it's a more complex structure which makes it much easier to asign a whole new array instead of looping through it and update each single element.

Help, ideas, .. are greatly appreciated as I couldn't find anything suitable in the net or I'm looking for the wrong phrases. ;

Replies are listed 'Best First'.
Re: Update references
by Khen1950fx (Canon) on May 13, 2012 at 15:43 UTC
    This might make is clearer:
    #!/usr/bin/perl -l use strict; no strict 'refs'; use warnings; use Devel::SimpleTrace; use Data::Dumper::Concise; print "With Arrays: "; my(@a) = qw(0 1 2 3); my $ar = \@a; my $air = \$a[0]; print "Define array >@a<\nCreate a reference to \$a[0]"; print "array ref: >@$ar<"; print "array index ref: >$$air"; @a = qw(a b c); $air = \$a[0]; print "Change array to >@a<"; print "array ref: >@$ar<"; print "array index ref: >${$air}<";

      The point is, that I don't want to renew the reference. I'm using this kind of reference for Tk-Checkbuttons and I'd have to recreate all of them (and there a quite a few).

      I thought, that a reference points to a place in your memory and doesn't care what's written in there. But it looks like I can't replace that piece of data by modifying the original array. Too me it looks a bit odd.
        But it looks like I can't replace that piece of data by modifying the original array.

        Of course you can, but you must not destroy the internal reference of the array slot [0] to the scalar originally stored in it.  If you do so, you have no access to that scalar any longer via $a[0].

        Change @a = ('a','b','c') to  pop @a; @a[0..2] = qw(a b c); and things will work fine.

        In the former case, 3 new scalars are being placed into the array slots, while in the latter case, the old scalars are being modified.

        #!/usr/bin/perl -w use strict; print "--------Trying with arrays-------\n"; my @a = (0, 1, 2, 3); my $ar = \@a; # Array reference my $air = \$a[0]; # Reference to member of an array print "Define array >@a<\nCreate a reference to \$a[0]\n"; print "array ref: >@$ar< \n"; print "array index ref: >$$air<\n"; pop @a; @a[0..2] = qw(a b c); print "Change array to >@a<\n"; print "array ref: >@$ar< \n"; print "array index ref: >$$air<\n"; # <--- I'd like to get "a" here __END__ --------Trying with arrays------- Define array >0 1 2 3< Create a reference to $a[0] array ref: >0 1 2 3< array index ref: >0< Change array to >a b c< array ref: >a b c< array index ref: >a<

        Your misunderstanding is that you think Perl works like C, i.e. that references directly point to the memory locations where the actual data is stored.  This is not how Perl works.

Re: Update references
by lidden (Curate) on May 13, 2012 at 18:43 UTC
Re: Update references
by stevieb (Canon) on May 13, 2012 at 20:08 UTC

    Can anyone explain *why* this is happening? I don't know enough of the perl innards to grasp it.

    When redefining @a, does Perl actually create a new array at a different memory location, leaving the old existing element simply because a reference still points to it?

      The reference refers to the scalar retrieved via $a[0], not the array index [0].  The reference knows nothing about the array that scalar came from.  And the scalar will exist as long as its refcount is > 0.

      $ perl -MDevel::Peek -E'@a=qw(a b c); $r=\$a[0]; Dump $r; @a=(); Dump +$r' SV = IV(0xa95bc0) at 0xa95bd0 REFCNT = 1 FLAGS = (ROK) RV = 0xa77998 SV = PV(0xa75c20) at 0xa77998 REFCNT = 2 <--- FLAGS = (POK,pPOK) PV = 0xa8ee40 "a"\0 CUR = 1 LEN = 16 SV = IV(0xa95bc0) at 0xa95bd0 REFCNT = 1 FLAGS = (ROK) RV = 0xa77998 SV = PV(0xa75c20) at 0xa77998 REFCNT = 1 <--- FLAGS = (POK,pPOK) PV = 0xa8ee40 "a"\0 CUR = 1 LEN = 16

      (note the refcounts)

        That's what I was after, and it makes complete sense. Thanks!

      I read in O'Reilly's Intermediate Perl Sec 5.2 that data stays alive until the last reference to it is destroyed.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://970288]
Approved by moritz
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (3)
As of 2023-11-29 05:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?