Dr.Ruud wrote:
>
> Rob Dixon schreef:
>>
>> Dr.Ruud wrote:
>>> 
>>> Rob Dixon wrote:
>>>> 
>>>> A scalar cannot have multiple 'personalities' - it can have a
>>>> maximum of two (its inherent type and a string equivalent) at any
>>>> one time, but usually has only one.
>>>
>>> It can at least have 3: an integer numeric one, a floating numeric
>>> one, and a string one. It can have more.
>>
>> No. It can be just a string; an integer and a string; a double and a
>> string; or a reference (pointer) and a string. After that there's
>> some weird stuff that goes on with tied scalars and so on. Basically
>> every scalar data type keeps space for a pointer to its string
>> equivalent as well, presumably because it's a useful thing to
>> remember once it has been evaluated once.
> 
> 
> 1: all three of IOK and NOK and POK are set.
> 
> perl -Mstrict -Mwarnings -MData::Dumper -MDevel::Peek=Dump -wle'
> 
>      my $s = "x";
>      defined($s) and do {
>          no warnings "numeric";
>          $s eq "" and 1;
>          $s == $_ and 1 for 0, 0.1;
>      };
>      print "\n", Dumper($s);
>      Dump $s;
> '
> 
> $VAR1 = 'x';
> 
> SV = PVNV(0x8a19cb8) at 0x89bad2c
>    REFCNT = 1
>    FLAGS = (PADBUSY,PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
>    IV = 0
>    NV = 0
>    PV = 0x89b6548 "x"\0
>    CUR = 1
>    LEN = 2
> 
> 
> 2: lossy, so no IOK.
> 
> perl -Mstrict -Mwarnings -MData::Dumper -MDevel::Peek=Dump -wle'
> 
>      my $s = "122.99999999999999";
>      defined($s) and do {
>          no warnings "numeric";
>          $s eq "" and 1;
>          $s == $_ and 1 for 0, 0.1;
>      };
>      print "\n", Dumper($s);
>      Dump $s;
> '
> 
> $VAR1 = '122.99999999999999';
> 
> SV = PVNV(0x88aba40) at 0x884cc3c
>   REFCNT = 1
>   FLAGS = (PADBUSY,PADMY,NOK,POK,pIOK,pNOK,pPOK)
>   IV = 122
>   NV = 123
>   PV = 0x8848700 "122.99999999999999"\0
>   CUR = 18
>   LEN = 19
> 
> 
> 3: a numeric string, touched by numeric comparisons, so returned as a
> number by Dumper; again all of IOK, NOK and POK are set.
> 
> perl -Mstrict -Mwarnings -MData::Dumper -MDevel::Peek=Dump -wle'
> 
>      my $s = "123";
>      $ARGV[0] and defined($s) and do {
>          no warnings "numeric";
>          $s eq "" and 1;
>          $s == $_ and 1 for 0, 0.1;
>      };
>      print "\n", Dumper($s);
>      Dump $s;
> ' 1
> 
> $VAR1 = 123;
> 
> SV = PVNV(0x8160dd0) at 0x8101be8
>   REFCNT = 1
>   FLAGS = (PADBUSY,PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
>   IV = 123
>   NV = 123
>   PV = 0x80fd450 "123"\0
>   CUR = 3
>   LEN = 4
> 
> 
> I would say that 1 and 3 have three personalities.
> And 2 has nearly three. :)

First of all I would say that all of these are NV values (double floats), and as
I have said scalar values always allow for PV (string) equivalents. What I was
unaware of was that the NV structure also includes space for an IV (integer)
equivalent. Other than that your results are as I described, and what you are
really defending is your comment here

> Dr.Ruud wrote:
> 
> There is no real way to test if a value inside a variable has a numeric 
> "personality". Variables can have multiple "personalities", each with there
> own binary value.

> Rob Dixon wrote:
> 
> A scalar cannot have multiple 'personalities' - it can have a maximum of two
> (its inherent type and a string equivalent) at any one time, but usually has
> only one. It will be given an additional string value only if it needs one for
> some reason. This is one reason why quoting variables - "$val" - is a bad idea
> in general, because it both forces conversion and occupies memory 
> unnecessarily.
> 
> There is indeed a simple way to test in Perl whether a scalar value is being
> treated as a string (I'm sure this is one or Randal's, but I can't find the
> reference)
> 
>   print "Non-string" if ($val & ~$val) eq '0';
> 
> And also, since Data::Dumper does it there clearly is a way for a module to do
> it in general.

And to be honest I think that if you're allowing 'multiple' to include 'three'
it may as well include 'two' as well :)

> 4: make $s blessed too.
> 
> perl -Mstrict -Mwarnings -MData::Dumper -MDevel::Peek=Dump -wle'
> 
>      my $s = "123";
>      bless \$s, "test";
>      defined($s) and do {
>          no warnings "numeric";
>          $s eq "" and 1;
>          $s == $_ and 1 for 0.1, 0;
>      };
>      print "\n", Dumper($s);
>      Dump $s;
> '
> 
> $VAR1 = 123;
> 
> SV = PVMG(0x90f5618) at 0x9068c44
>   REFCNT = 1
>   FLAGS = (PADBUSY,PADMY,OBJECT,IOK,NOK,POK,pIOK,pNOK,pPOK)
>   IV = 123
>   NV = 123
>   PV = 0x9064460 "123"\0
>   CUR = 3
>   LEN = 4
>   STASH = 0x9063cf4     "test"
> 
> That last one is an example of what I named "more".

A PVMG is a 'magical', and that is a whole separate consideration that I don't
think belongs here.

I hope it summarises this thread to your satisfaction if I make these points

- A simple scalar variable may have up to three valid values simultaneously: a
  string value, and integer value, and a double float value

- It is straightforward for a Perl module with a C component to examine which
  values are valid, and behave accordingly

- Forcing a conversion to a string or a numeric is easy in Perl, using

    $val.''
  or
    $val+0

  respectively.


Just to make things worse, I see that Perl 5.10 has moved the pointer to the
string value from the body of the structure up to the header, so that it is now
svu_pv instead of xp_pv. Also, string and integer structures (xpv and xpviv) now
have space for a double value as well. Oddly though, there is no allowance in
xpv for an integer value. This stuff has stayed pretty much constant since Perl
5.4 and it seems I have a lot of reading to do!

Rob

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to