in reply to Question on SV internals

Now if I perform another numeric operation on that value, does it remember that it was 20 and not convert it again?

Short answer: Yes, until you next use it in a string context.

Ie.

@a = 1 .. 1e6;; print total_size \@a;; 32000176 "$_" for @a;; Useless use of string in void context at (eval 11) print total_size \@a;; 72000176 @a = 1 .. 1e6;; print total_size \@a;; 32000176 ''.$_ for @a;; Useless use of concatenation (.) or string in void context at (eval 15 +) print total_size \@a;; 72000176

What the above shows is that apparently innocent and even useless references to numeric scalars in string contexts can cause a quite dramatic explosion in memory usage.

Most of the time, individual scalars and small aggregates, this is inconsequential, but if you are dealing with large aggregates close to the limits of your memory, it can be worth your while to take care to prevent such conversions:

@a = 1 .. 1e6;; print total_size \@a;; 32000176 do{ my $n = $_; "$n" } for @a;; Useless use of string in void context at (eval 23) line 1, <STDIN> lin +e 15. print total_size \@a;; 32000176

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".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: Question on SV internals
by ikegami (Patriarch) on May 08, 2011 at 15:54 UTC

    Yes, until you next use it in a string context.

    There's no such terminating condition.

    >perl -MDevel::Peek -e"$_ = '20 ducks'; Dump($_); 0+$_; Dump($_); ''.$ +_; Dump($_);" ... SV = PVNV(0x163a454) at 0x342be4 REFCNT = 1 FLAGS = (POK,pIOK,pNOK,pPOK) IV = 20 NV = 20 PV = 0x1639b14 "20 ducks"\0 CUR = 8 LEN = 12

    Another way to check is to count the number of numeric warnings:

    >perl -wE"$_='20 ducks'; say 0+$_; say 0+$_; say ''.$_; say 0+$_;" Argument "20 ducks" isn't numeric in addition (+) at -e line 1. 20 20 20 ducks 20

      $s = '20 ducks';; Dump $s;; SV = PV(0x18aec0) at 0xa5b48 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x40cad18 "20 ducks"\0 CUR = 8 LEN = 16

      Length = 16. Now use it in a numeric constant.

      $s += 1;; Argument "20 ducks" isn't numeric in addition (+) at (eval 13) line 1, + <STDIN> line 4. Dump $s;; SV = PVNV(0x40b1eb8) at 0xa5b48 REFCNT = 1 FLAGS = (NOK,pNOK) IV = 20 NV = 21 PV = 0x40cad18 "20 ducks"\0 CUR = 8 LEN = 16

      Hm. Length still 16, but we gained an IV = 20 and an NV = 21; so we gained 12 or 16 bytes.

      Oh, and the PV no longer reflects the value of the scalar, so when you use it in a string context, a conversion has to happen!

      print $s;; 21 Dump $s;; SV = PVNV(0x40b1eb8) at 0xa5b48 REFCNT = 1 FLAGS = (NOK,POK,pNOK,pPOK) IV = 20 NV = 21 PV = 0x40d3068 "21"\0 CUR = 2 LEN = 40

      Which modifies the PV and oops, it grew to 40 bytes in the process.

      And I don't care how you try to weasel out of it, the evidence is right there for those that care to look. So don't bother.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Now use it in a numeric constant. $s += 1;

        $s += 1 does more than "use it in a numeric context".

        Update:

        Furthermore, even though you went outside the scope of the question, the scalar still has a numerical value throughout.

          FLAGS = (NOK,pNOK)
          FLAGS = (NOK,POK,pNOK,pPOK)

        There is no such terminating condition.