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: <%-{-{-{-<
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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,
| [reply] [d/l] [select] |
|
|
|
|
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.
| [reply] |
|
|
|
|
|
|
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 );
| [reply] [d/l] [select] |
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.
In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
| [reply] [d/l] [select] |
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".
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] |
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
|
| [reply] [d/l] [select] |