Data can get unshared on read as well—for example, when a numerical variable is accessed as a string. Example 10-7 shows some code that proves this.

Example 10-7. numerical_vs_string.pl

#!/usr/bin/perl -w

use Devel::Peek;
my $numerical = 10;
my $string    = "10";
$|=1;

dump_numerical( );
read_numerical_as_numerical( );
dump_numerical( );
read_numerical_as_string( );
dump_numerical( );

dump_string( );
read_string_as_numerical( );
dump_string( );
read_string_as_string( );
dump_string( );

sub read_numerical_as_numerical {
    print "\nReading numerical as numerical: ", int($numerical), "\n";
}
sub read_numerical_as_string {
    print "\nReading numerical as string: ", "$numerical", "\n";
}
sub read_string_as_numerical {
    print "\nReading string as numerical: ", int($string), "\n";
}
sub read_string_as_string {
    print "\nReading string as string: ", "$string", "\n";
}
sub dump_numerical {
    print "\nDumping a numerical variable\n";
    Dump($numerical);
}
sub dump_string {
    print "\nDumping a string variable\n";
    Dump($string);
}

The test script defines two lexical variables: a number and a string. Perl doesn't have strong data types like C does; Perl's scalar variables can be accessed as strings and numbers, and Perl will try to return the equivalent numerical value of the string if it is accessed as a number, and vice versa. The initial internal representation is based on the initially assigned value: a numerical value[37] in the case of $numerical and a string value[38] in the case of $string.

[37]IV, for signed integer value, or a few other possible types for floating-point and unsigned integer representations.

[38]PV, for pointer value (SV is already taken by a scalar data type)

The script accesses $numerical as a number and then as a string. The internal representation is printed before and after each access. The same test is performed with a variable that was initially defined as a string ($string).

When we run the script, we get the following output:

Dumping a numerical variable
SV = IV(0x80e74c0) at 0x80e482c
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 10

Reading numerical as numerical: 10

Dumping a numerical variable
SV = PVNV(0x810f960) at 0x80e482c
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK)
  IV = 10
  NV = 10
  PV = 0

Reading numerical as string: 10

Dumping a numerical variable
SV = PVNV(0x810f960) at 0x80e482c
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
  IV = 10
  NV = 10
  PV = 0x80e78b0 "10"\0
  CUR = 2
  LEN = 28

Dumping a string variable
SV = PV(0x80cb87c) at 0x80e8190
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,POK,pPOK)
  PV = 0x810f518 "10"\0
  CUR = 2
  LEN = 3

Reading string as numerical: 10

Dumping a string variable
SV = PVNV(0x80e78d0) at 0x80e8190
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,NOK,POK,pNOK,pPOK)
  IV = 0
  NV = 10
  PV = 0x810f518 "10"\0
  CUR = 2
  LEN = 3

Reading string as string: 10

Dumping a string variable
SV = PVNV(0x80e78d0) at 0x80e8190
  REFCNT = 4
  FLAGS = (PADBUSY,PADMY,NOK,POK,pNOK,pPOK)
  IV = 0
  NV = 10
  PV = 0x810f518 "10"\0
  CUR = 2
  LEN = 3

We know that Perl does the conversion from one type to another on the fly, and that's where the variables get modified—during the automatic conversion behind the scenes. From this simple test you can see that variables may change internally when accessed in different contexts. Notice that even when a numerical variable is accessed as a number for the first time, its internals change, as Perl has intialized its PV and NV fields (the string and floating-point represenations) and adjusted the FLAGS fields.

From this example you can clearly see that if you want your variables to stay shared and there is a chance that the same variable will be accessed both as a string and as a numerical value, you have to access this variable as a numerical and as a string, as in the above example, before the fork happens (e.g., in the startup file). This ensures that the variable will be shared if no one modifies its value. Of course, if some other variable in the same page happens to change its value, the page will become unshared anyway.