in reply to Why do I (sometimes) get a REF ref and not a SCALAR ref?

I would explain it slightly differently than BrowserUk.

$ perl -le 'my $a = "foo"; $a = \$a; print $a'
REF(0x7f9b608299c8)

In this example, a reference to  $a is assigned to  $a and the whole thing becomes circular; $a refers to $a, which refers to $a, ... So $a is a REF to $a (to $a, to ...) If the magical names  $a and  $b are avoided and everything is made lexical to keep everyone honest and aboveboard (nothing up my sleeve...):

c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 'foo'; $x = \$x; print $x; print $$x; print $$$x; print $$$$x; " REF(0x1df2a9c) REF(0x1df2a9c) REF(0x1df2a9c) REF(0x1df2a9c)
Note that the reference addresses are all the same.

$ perl -le 'my $a = "foo"; my $b = \$a; $a = $b; print $a'
REF(0x7fab830299c8)

This example is a bit more roundabout in that it first assigns a reference to  $a to another scalar before assigning it back to  $a to establish circularity, but the result is the same:

c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 'foo'; my $y = \$x; $x = $y; print $x; print $$x; print $$$x; print $$$$x; " REF(0x601cec) REF(0x601cec) REF(0x601cec) REF(0x601cec)
Again, all the reference addresses are the same.

In all these examples, the original value of $x (or $a in the OPed code), 'foo', is lost.

Update: Or entirely without circularity:

c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $w = 'foo'; my $x = \$w; my $y = \$x; my $z = \$y; ;; print $z; print $$z; print $$$z; print $$$$z; ;; dd $z; " REF(0x54c11c) REF(0x432734) SCALAR(0x4326f4) foo \\\"foo"


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

Replies are listed 'Best First'.
Re^2: Why do I (sometimes) get a REF ref and not a SCALAR ref?
by kennethk (Abbot) on Jun 23, 2016 at 14:55 UTC
    It's worth noting that circularity is not required, nor is it required that you are dealing with a scalar:
    perl -E 'say \\$x; say \\@x; say \\%x'
    outputs
    REF(0x735d48) REF(0x735d48) REF(0x735d48)
    Seems like an odd design choice since it makes crawling an arbitrary reference tree harder and I wouldn't think it adds any useful information. Anyone know a justification?

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Interestingly, using all the expressions in one command:
      perl -E 'say for \\$x, \\@x, \\%x;'

      gives a different output:

      REF(0x1204e78) REF(0x12251f8) REF(0x1225240)

      If you don't store the reference, it's freed and reused later.

      $ perl -E 'say \\$x; say \\@y; say \\%z;' REF(0xcfae78) REF(0xcfae78) REF(0xcfae78)

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        To finish the set:
        perl -E '@arr=(\\$x,\\@x,\\%x);say \\$x;say \\@x;say \\%x'
        outputs
        REF(0x8e8f58) REF(0x8e8f58) REF(0x8e8f58)
        and
        perl -E '@arr=(\\$x,\\@x,\\%x);say join"\n",\\$x,\\@x,\\%x'
        outputs
        REF(0xdc3f58) REF(0xdc3e38) REF(0xde0618)
        and
        perl -E '@arr=(\\$x,\\@x,\\%x);say $arr[0];say $arr[1];say $arr[2]'
        outputs
        REF(0x19b4d48) REF(0x19b4b98) REF(0x19d13e8)
        I think what's going on is that we're getting the address of a temporary variable. When they are all in the same statement, you need three temporary spots; when in different statements, you just reuse your scratch space.

        Still doesn't answer the 'REF' question, though...


        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      My understanding is the three variables you listed are actually stored in the same dictionary entry, but as 'x (as a scalar)', 'x (as an array)' and 'x (as a hash)'. The appropriate value or list is returned based on the context.

      Alex / talexb / Toronto

      Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

        Package vars are stored in an instance of a struct called a typeglob, glob or GV.

        The appropriate variable is fetched when needed.

        $ perl -E' say \*x; # Prints the address of the glob. say \@x; # Prints the address of the array. say *x{ARRAY}; # Prints the address of the same array. say \%x; # Prints the address of the hash. say *x{HASH}; # Prints the address of the same hash. ' GLOB(0x2f78fd8) ARRAY(0x2f79080) ARRAY(0x2f79080) HASH(0x2f79038) HASH(0x2f79038)

        None of this is relevant here. The program is printing the address of three different anonymous scalars that all got allocated at the same address (which is possible since none of the three existed at the same time).

        That's what I thought, but choroba's reply implies it's just really fast garbage collection or persistent scratch space. This gets into deeper waters than I'm used to.

        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re^2: Why do I (sometimes) get a REF ref and not a SCALAR ref?
by Anonymous Monk on Jun 23, 2016 at 12:33 UTC

    Thanks very much to all responders. Now it makes sense. Somehow I was thinking $x = \$x took a reference to the value in $x, not $x itself. And yes, $a and $b were ill-chosen.

    The code that gave rise to this was creating a PPI::Document. This takes as its first argument either a file name or a scalar reference to the literal code to be analyzed. I wanted my wrapper to treat its argument as a file if it represented an extant file, otherwise as literal code. My code started out PPI::Document->new( -e $arg ? $arg : \$arg ), which worked fine. Then as the code became more complex I decided I wanted to move the test elsewhere, which gave rise to -e $arg and $arg = \$arg;. The final iteration of the relevant code was -e $arg and $arg = \( my $temp = $arg );