4

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.

3
  • 3
    Even if you could do what you were trying to do, the original content would be gone because of reference counting. Just use a different variable for the reference. Commented Sep 20, 2017 at 14:58
  • @AKHolland oh, right... I did not think of the reference counting... Commented Sep 20, 2017 at 15:18
  • 1
    @AKHolland, Nonsense. It can't be gone if it's still accessible. If the OP could do what they are trying to do (access the original value as $$x), then it would be a major bug in Perl if its reference count had reached zero. Commented Sep 21, 2017 at 3:44

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

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

print $$string, "\n";

8 Comments

But wouldn't this make a copy of the string? Wouldn't "abcefgh" and "$string" exist in the same time?
@soger: So create it right at the beginning: my $string = \ 'abcdefgh';.
real life is not that simple.
@soger: What is wrong with duplicating the string? Short of writing some C code it is the only way to get a reference to the variable's content instead of to the variable itself. I can't see it being a problem unless the string holds multiple gigabytes.
You copy the value, but need to just get reference to it. see stackoverflow.com/a/46325686/1336858
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.