in reply to What does my @x= (undef)x7; do?

Update: In most cases...(but not this one. Thanks, Athanasius.)

FWIW: The same thing can be achieved by my @x; $#x = 6;


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^2: What does my @x= (undef)x7; do?
by Athanasius (Archbishop) on Nov 09, 2015 at 15:19 UTC

    Yes, it should work; but, strangely, it doesn’t:

    #! perl use strict; use warnings; use Data::Dump; use Win32API::File qw(getLogicalDrives GetVolumeInformation); my @drives = getLogicalDrives(); for my $d (@drives) { # my @x = (undef) x 7; my @x; $#x = 6; # dd \@x; GetVolumeInformation($d, @x); print "$d $x[0] ($x[5])\n"; }

    Output:

    1:16 >perl 1442_SoPW.pl Modification of a read-only value attempted at C:/Perl/Strawberry/stra +wberry-perl-5.22.0.1-64bit-PDL/perl/lib/Win32API/File.pm line 269. 1:16 >

    But with the line dd \@x; uncommented, it does work:

    1:16 >perl 1442_SoPW.pl [undef, undef, undef, undef, undef, undef, undef] C:\ (NTFS) [undef, undef, undef, undef, undef, undef, undef] D:\ () [undef, undef, undef, undef, undef, undef, undef] E:\ () 1:16 >

    What’s going on?

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

      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.
        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.