Re: Dualvars besides $!
by davido (Cardinal) on Jan 27, 2014 at 17:41 UTC
|
I think you are misinterpreting the results of your test. (No, I was misunderstanding what point was being made. ;)
Scalar::Util::isdual returns a true value if the variable being tested is a dualvar. Your test indicates that isdual is returning 1 when tested against $!, which is a true value, indicating that $! is a dualvar.
Update: A list of "dualvar" special variables, as I find them.
- $( The documentation eludes to this; it may contain a space-delimited list (a string), but you can only assign a number to it.
- $) The documentation is similar on this one, and it too is a dualvar.
- $^E The POD says "Caveats mentioned in the description of $! generally apply to $^E , also."
Also, since $_ implicitly topicalizes a foreach loop, and since it's an alias to an iteration's topic, it can be made to appear to be a dualvar:
for ( $! ) {
print Scalar::Util::isdual($_), "\n";
}
...outputs '1', because in this case $_ is an alias to a dualvar. So we can add to the list:
- Any variable that aliases a dualvar becomes a dualvar while the alias is in effect (consider foreach ( $! ) { # $_ is a dualvar here })
| [reply] [d/l] [select] |
|
That's my point.
dualvar indicates that $! is indeed a dualvar but the documentation of Scalar::Util say $! is not a dualvar. Or did I misunderstand what the documentation claims?
| [reply] |
|
| [reply] [d/l] |
Re: Dualvars besides $!
by moritz (Cardinal) on Jan 27, 2014 at 17:11 UTC
|
Not a variable, but a value: the value for false, which you can generate with !1.
It return '' in string context and 0 in numeric context, and doesn't warn in numeric context like the empty string normally does:
$ perl -wE 'say 0+""'
Argument "" isn't numeric in addition (+) at -e line 1.
0
$ perl -wE 'say 0+!1'
0
My version of Scalar::Util doesn't export an is_dual function, so I can't check. It helps to type that without the _ :-)
Update: I should have mentioned it earlier: even though the thing is called a "dualvar", it's not actually variables that are tested; values are being tested. It makes no difference if those values are return values, stored in array, or are stored in a scalar variable.
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
wow !1. I have not heard of that earlier. greping the pods of 5.18.2 - it is not mentioned there either. But it works as you showed.
| [reply] |
Re: Dualvars besides $!
by ikegami (Patriarch) on Jan 27, 2014 at 20:36 UTC
|
$ perl -MScalar::Util=isdual -E'
$x=1; say isdual($x)?1:0;
"$x"; say isdual($x)?1:0;
'
0
1
The stringification is cached. | [reply] [d/l] |
|
IMHO, that's a rather stupid interpretation of "dualvar". If the string value equals the stringification of the other value (IV or NV), then it shouldn't be considered a "dualvar". But then, that's what one would expect from a lazy XS function. A Perl version would just do 0+$x eq $x instead.
!1 doesn't need to be implemented as a dualvar. $x=''; {no warnings; 0+$x;} is also enough to get you what is needed for !1 (a string value of '' and a numeric value of 0 w/o a warning). The canonical value for !1 that Perl uses happens to be a real dualvar, though. But "both an empty string and zero" isn't enough to imply "dualvar".
Win32::TieRegistry can use dualvars.
Update: To be clearer, a Perl version of isdual() would be:
sub isdual {
my( $v ) = @_;
no warnings;
return 0
if int $v ne $v^'0' # No IV nor NV in value
|| $v eq 0+$v # Cached string just same as IV/NV
|| $v == "$v" # Cached number just same as 0+PV
;
return 1;
}
| [reply] [d/l] [select] |
|
The stringification is cached.
This is a good point. Is this good rule of thumb (bound to be imperfect but close enough)? Anytime an SV with an IV or NV creates a PV representation, that will remain in effect (making it a dualvar) until the container receives a new assignment.
| [reply] |
|
say "!",$x,"!"; doesn't, but "everything else" does.
| [reply] [d/l] |
|
$ perl -MData::Peek -wC3 \
-E'my $tv = Data::Peek::triplevar ("\N{GREEK SMALL LETTER PI}", 3, 3.1415);' \
-e'say for map { $_ // "<undef>" } DDual ($tv)'
π
3
3.1415
<undef>
0
Data::Peek's DDual will return all of those: my ($pv, $iv, $nv, $rv, $hm) = DDual ($var [, $getmagic])
Enjoy, Have FUN! H.Merijn
| [reply] [d/l] [select] |
Re: Dualvars besides $!
by ikegami (Patriarch) on Jan 27, 2014 at 19:54 UTC
|
perl -MDevel::Peek -e'$!=1; print("$!\n"); Dump($!);'
5.8.9:
...
FLAGS = (GMG,SMG,pNOK,pPOK)
...
No public values. Not a dualvar.
5.18.1:
...
FLAGS = (GMG,SMG,NOK,POK,pNOK,pPOK)
...
Two public values (NOK = has NV = has floating point number, POK = has PV = has string). Dualvar.
| [reply] [d/l] [select] |
|
The latest Scalar::Util::isdual considers FLAGS = (GMG,SMG,pNOK,pPOK) to be a dualvar. (No idea about earlier versions, but I suspect it's the same.) The docs are wrong. The following returns 1 for both 5.8.9 and 5.18.1, while the docs say it returns false:
perl -MScalar::Util=isdual -MDevel::Peek \
-e'$!=1; print("$!\n"); print(isdual($!)?1:0,"\n"); Dump($!);'
Nit: $! is magical (like tied variables), but it's not a tied variable like the docs say. | [reply] [d/l] [select] |