Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re^3: What does my @x= (undef)x7; do?

by BrowserUk (Patriarch)
on Nov 09, 2015 at 15:32 UTC ( [id://1147260]=note: print w/replies, xml ) Need Help??


in reply to Re^2: What does my @x= (undef)x7; do?
in thread What does my @x= (undef)x7; do?

What’s going on?

The explicit method populates the array with 7 physical pointers to undef:

[0] Perl> @x = (undef)x7;; [0] Perl> use Devel::Peek;; [No such file or directory] Perl> Dump \@x;; SV = RV(0x3c735d0) at 0x3c735c0 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x3c6ac88 SV = PVAV(0x3cfafd8) at 0x3c6ac88 REFCNT = 2 FLAGS = (RMG) MAGIC = 0x3cee198 MG_VIRTUAL = &PL_vtbl_arylen_p MG_TYPE = PERL_MAGIC_arylen_p(@) MG_FLAGS = 0x02 REFCOUNTED MG_OBJ = 0x3c6a410 SV = PVMG(0x3b1a078) at 0x3c6a410 REFCNT = 1 FLAGS = (GMG,SMG,pIOK) IV = 6 NV = 0 PV = 0 MAGIC = 0x3ceea08 MG_VIRTUAL = &PL_vtbl_arylen MG_TYPE = PERL_MAGIC_arylen(#) MG_OBJ = 0x3c6ac88 ARRAY = 0x3cf1398 FILL = 6 MAX = 7 ARYLEN = 0x3c6a410 FLAGS = (REAL) Elt No. 0 SV = NULL(0x0) at 0x3cb4b98 REFCNT = 1 FLAGS = () Elt No. 1 SV = NULL(0x0) at 0x3c73578 REFCNT = 1 FLAGS = () Elt No. 2 SV = NULL(0x0) at 0x3cb49b8 REFCNT = 1 FLAGS = () Elt No. 3 SV = NULL(0x0) at 0x3cb4af0 REFCNT = 1 FLAGS = ()

Whereas, when you pre-extend the array, no physical pointer are populated; the undef's are implied by the absence of pointers:

[0] Perl> undef @x;; [0] Perl> $#x = 6;; [0] Perl> Dump \@x;; SV = RV(0x3c735d0) at 0x3c735c0 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x3c6ac88 SV = PVAV(0x3cfafd8) at 0x3c6ac88 REFCNT = 2 FLAGS = (RMG) MAGIC = 0x3cee198 MG_VIRTUAL = &PL_vtbl_arylen_p MG_TYPE = PERL_MAGIC_arylen_p(@) MG_FLAGS = 0x02 REFCOUNTED MG_OBJ = 0x3c6a410 SV = PVMG(0x3b1a078) at 0x3c6a410 REFCNT = 1 FLAGS = (GMG,SMG,pIOK) IV = 6 NV = 0 PV = 0 MAGIC = 0x3ceea08 MG_VIRTUAL = &PL_vtbl_arylen MG_TYPE = PERL_MAGIC_arylen(#) MG_OBJ = 0x3c6ac88 ARRAY = 0x3cf1398 FILL = 6 MAX = 6 ARYLEN = 0x3c6a410 FLAGS = (REAL) Elt No. 0 Elt No. 1 Elt No. 2 Elt No. 3

Perl code would treat the two the as the same, but user-written XS code makes assumptions.

Thanks for checking it.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^4: What does my @x= (undef)x7; do?
by betterworld (Curate) on Nov 09, 2015 at 17:53 UTC
    Perl code would treat the two the as the same, but user-written XS code makes assumptions.

    When I read this, I felt an urge to find Perl code that behaves differently for these arrays :)

    Turns out that what this API function is doing would require explicit undefs even if the function was written in Perl. This is a subroutine that modifies its input parameters. In Perl you might write it like this:

    use Data::Dumper; my @a; @a = (undef) x 5; my @b; $#b = 4; sub modify { $_ = 5 for @_; } modify(@a); print Dumper \@a; modify(@b); print Dumper \@b;

    Here the subroutine "modify" behaves similar to GetVolumeInformation as it modifies the scalars in the array passed to it.

    So the arrays @a and @b should be identical. However, modify() will replace @a with five times 5, but it cannot write to @b:

    $VAR1 = [ 5, 5, 5, 5, 5 ]; Modification of a read-only value attempted at script.pl line 12.

    Update: Since this seems to depend on the version: I am using Perl 5.20.2 on Debian.

      I don't see your pure-Perl "Modification of a read-only value..." result on ActiveState 5.8.9 and Strawberry 5.14.4.1 (Update: likewise Strawberries 5.10.1.5 and 5.12.3.0), but there's something else I don't understand:

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "sub modify { $_ = 5 for @_; } ;; my @a; @a = (undef) x 5; ;; modify(@a); print Dumper \@a; ;; my @b; $#b = 4; ;; modify(@b); print Dumper \@b; ;; my @c; $#c = 4; $c[ $#c ] = undef; ;; modify(@c); print Dumper \@c; " $VAR1 = [ 5, 5, 5, 5, 5 ]; $VAR1 = [ undef, undef, undef, undef, undef ]; $VAR1 = [ undef, undef, undef, undef, 5 ];
      Arrays @b and @c are still unwriteable (or at least unwritten, at least in part), but in a different way.   ?!?

      Update: Taking the  @_ argument list out of the equation, I get expected results (thank Larry!) for the problematic cases above (for all Perl versions listed in the first paragraph):

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "my @b; $#b = 4; ;; $_ = 5 for @b; print Dumper \@b; ;; my @c; $#c = 4; $c[ $#c ] = undef; ;; $_ = 6 for @c; print Dumper \@c; " $VAR1 = [ 5, 5, 5, 5, 5 ]; $VAR1 = [ 6, 6, 6, 6, 6 ];


      Give a man a fish:  <%-{-{-{-<

      You do realise that you aren't passing the array into modify()? You're passing a list. And that list is being aliased.

      And prior to the mostly pointless, blanket constanisation of the Perl sources, the (incorrect) attribution of a null C pointer to a scalar would not have been spuriously attributed to a "read-only value".

      Two mistakes collide here:

      1. The lazy definition of an api that takes a list of pre-existing and defined variables as input in order to provide output.
      2. The retroactive application of const'ing at the C-level with callous disregard to the affects at the Perl level.

      Upshot: p5p have buggered Perl5 in their attempts to 'be correct'.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice.
        You do realise that you aren't passing the array into modify()? You're passing a list. And that list is being aliased.

        Yes I do :) It's a list of aliases, just like in the subroutine GetVolumeInformation from the original post.

        p5p have buggered Perl5 in their attempts to 'be correct'.

        I think this is related to some optimization. Some people like to use $#array = ... because it is faster than explicitly filling the array. However this optimization comes with a cost.

        Assigning to the length does not put any SVs into the new elements, and this is why you cannot create references or aliases to them. I thought there was something about this in the documentation, but I cannot find it any more (only a related section in perlguts)

        I would be very interested in any comments you might have on the, to me, very puzzling behavior seen when iterating over the aliased  @_ argument list with arrays  @b and  @c in the  modify() function in the reply above. I have only been able to confirm this behavior in the older Perl versions noted therein.


        Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-03-28 16:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found