soger
soger

Reputation: 1237

Make variable reference its own string content

I wanted to make a variable reference its own content so I did this:

$x=\$x;

but that does not work as I expected, $x became a reference to itself so $$x is the same as $x. What I was expecting is that $$x becomes the original string. Why is that and how should I write it correctly without making a copy of the string in $x? Because in some cases $x can be a huge string.

Upvotes: 4

Views: 431

Answers (2)

ikegami
ikegami

Reputation: 386656

What you are asking is impossible. A variable can't contain both a reference and a string. You must utilize two variables. This leaves you with two options.

Store the reference in a new variable

$ perl -e'
   use feature qw( say );
   my $x = "abc";
   my $y = \$x;
   say $y;
   say $$y;
'
SCALAR(0x232a398)
abc

Nice and simple, efficient, and no confusion as to what the variable contains at what time.

The downside of this approach is that references to the original $x won't see the change. It's hard to imagine a situation where this would matter, however.

Note that the new var could even have the same name as the old one. I don't recommend this as it's needlessly confusing and error-prone.

$ perl -e'
   use feature qw( say );
   my $x = "abc";
   my $x = \$x;
   say $x;
   say $$x;
'
SCALAR(0x232a398)
abc

Store the value in a new variable

$ perl -e'
   use feature qw( say );
   my $x = "abc";
   $x = \( my $container = $x );
   say $x;
   say $$x;
'
SCALAR(0x175cbe0)
abc

The downside of this approach is it involves copying the string. However, that's only the case until 5.20. 5.20 introduced a copy-on-write mechanism for strings. That means the above won't actually copy the string in 5.20+; it will just copy a pointer instead. Note that both scalars share the same string buffer (0x2ac53d0) in the following example:

$ perl -MDevel::Peek -e'my $x = "abc"; my $y = $x; Dump($_) for $x, $y;' 2>&1 \
   | grep -P '^(?:SV|  FLAGS|  PV)\b'
SV = PV(0x2a9f0c0) at 0x2abcdc8
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x2ac53d0 "abc"\0
SV = PV(0x2a9f150) at 0x2abcde0
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x2ac53d0 "abc"\0

While $x = \"$x" has been suggested as a shorter version of $x = \( my $container = $x );, it forces stringification, and it copies the entire string, even in versions of Perl that support COW.

Upvotes: 4

choroba
choroba

Reputation: 242333

Assign a reference to the value, not to the variable:

my $string = 'abcefgh';
$string = \ "$string";

print $$string, "\n";

Upvotes: 1

Related Questions