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

Can anyone give an explanation of the following Perl behavior?

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

What I would expect is for all the above to produce a SCALAR. I'm tempted to call this a bug, but I have gotten this behavior with 5.25.2, 5.24.0, 5.22.2, 5.20.2, and 5.8.9, so you would think if it was a bug someone would have noticed before now. So what gives?

  • Comment on Why do I (sometimes) get a REF ref and not a SCALAR ref?

Replies are listed 'Best First'.
Re: Why do I (sometimes) get a REF ref and not a SCALAR ref?
by AnomalousMonk (Archbishop) on Jun 23, 2016 at 06:14 UTC

    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:  <%-{-{-{-<

      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,

        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.

      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 );

Re: Why do I (sometimes) get a REF ref and not a SCALAR ref?
by BrowserUk (Patriarch) on Jun 23, 2016 at 04:41 UTC

    This ($b) is a scalar ref: my $a; my $b = \$a;; this ($c) is a reference to a reference: my $a; my $b = \$a; my $c = \$b;

    A REF(0xxxxxx) is a reference to a reference. Ie. Above $c is the same as my $a; my $c = \\$a;.

    More succincly:

    my $a; my $b = \$a; print $b; SCALAR(0x3e6c920) my $c = \$b; print $c; REF(0x3e6c8f0) print \\$a;; REF(0x3e6c980)

    And:

    my $a = 'fred'; my $b = \$a; print $b, ' ', $$b; SCALAR(0x3e6c980) fred my $c = \$b; print $c, ' ', $$c, ' ', $$$c;; REF(0xf5e58) SCALAR(0x3e6c980) fred

    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. Not understood.
Re: Why do I (sometimes) get a REF ref and not a SCALAR ref? (silly)
by tye (Sage) on Jun 23, 2016 at 18:39 UTC

    Yeah, you can explain this behavior. But it is, frankly, stupid. \\$x is, indeed, a reference to a scalar and so ref should return "SCALAR". Having a special case for "reference to a scalar that happens to currently be holding a reference" is silly. It just leads to code having to check for both "SCALAR" and "REF", adding complexity. It makes about as much sense as having ref(\\\$x) return "REFREF" or ref(\\@x) return "ARRAYREF" or ref([]) return "EMPTYARRAY".

    - tye        

      The "ARRAY" references can be dereferenced via @{ $ref }.
      The "HASH" references can be dereferenced via %{ $ref }.
      The "REF" references can be dereferenced via ${ $ref }.

      Silly or not, but a self-circular reference can be followed ad infinitum; you never arrive at plain "SCALAR" value.

        Circularity has nothing to do with whether "REF" or "SCALAR" is returned. "SCALAR" references can be dereferenced via ${ $ref }, exactly like "REF" references, which argues for not making that distinction. Code that is going to traverse from $sv to $$sv is often also code that will traverse from checking ref $av to checking ref $av->[0] and from checking ref $hv to checking ref $hv->{$key} and so can cycle infinitely for any of those cases.

        - tye        

        Uh, addendum. (Getting confused myself?) I should've said:

        Both "SCALAR" and "REF" can be dereferenced via ${ $ref }, but only the "SCALAR" can be used as a honest scalar via that deref.

Re: Why do I (sometimes) get a REF ref and not a SCALAR ref?
by ikegami (Patriarch) on Jun 24, 2016 at 17:01 UTC

    The string is based on the referenced variable.

    • If the variable is a hash, the string is HASH.
    • If the variable is an array, the string is ARRAY.
    • If the variable contains an array, the string is REF.
    • ...
    • Otherwise, the string is SCALAR.

    So,

    1. You are printing a reference to $a, which contains "foo": SCALAR
    2. You are printing a reference to $a, which contains \$a: REF
    3. You are printing a reference to $b, which contains "foo": SCALAR
    4. You are printing a reference to $a, which contains \$a: REF