On Thu, Jul 6, 2017 at 9:38 AM hw <h...@gc-24.de> wrote: > Chas. Owens wrote: > > > > > > On Sat, Jul 1, 2017, 12:44 Shlomi Fish <shlo...@shlomifish.org <mailto: > shlo...@shlomifish.org>> wrote: > > > > Hi Shawn! > > > > On Sat, 1 Jul 2017 11:32:30 -0400 > > Shawn H Corey <shawnhco...@gmail.com <mailto:shawnhco...@gmail.com>> > wrote: > > > > > !!$i which is !(!(0)) which is !(1) which is 0 > > > > > > > I suspect !1 returns an empty string in scalar context. > > > > > > !1 returns PL_sv_no (an internal scalar variable). It is a dualvar that > contains the empty string, the int 0 and the double 0.0. depending on the > context the value is used in, it will be one of those values. > > > > Many people think it is an empty string because the print function > forces string context. > > > > > perl -e 'my $i =0; $i = defined($i) ? (!!$i) : 0; use Data::Dumper; print > Dumper($i);' > > > A printing function should not force a context but use the context it is > operating in. > > How do you print something without having a string context enforced upon > you? >
String context will always be force by printing (you don't print integers, you print characters). If you want to ensure that a dualvar uses the double (or integer if the double doesn't exist), you use the venus secret operator (so named because it looks like the Greek symbol for Venus ♀): 0+. Secret operators aren't really operators (or secret), but are just a set of operators and arguments that are used idiomatically. for example: perl -E 'my $i = !!0; print "\$i as a string: [$i]\n\$i as an int: [", 0+$i, "]\n"' $i as a string: [] $i as an int: [0] Data::Dumper is not the best way to see what a variable holds if you care about types. The Devel::Peek module gives you a much better picture, but you do need to know a bit about perl (ie the interpreter) to understand it (because Perl, the language, doesn't care about types): perl -MDevel::Peek -E 'my $i = !!0; Dump $i' SV = PVNV(0x7f88488036b0) at 0x7f884882a0b8 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x7f8848405180 ""\0 CUR = 0 LEN = 10 Here we can see that $i is a PVNV, that is it holds a string (Pointer Value) and a number (Number Value). The flags IOK, NOK, and POK tell us that the IV (integer), NV (double), and PV (string) portions are all safe to use. Now let's look at $i after the venus secret operator runs: perl -MDevel::Peek -E 'my $i = 0+!!0; Dump $i' SV = IV(0x7febe102a0a8) at 0x7febe102a0b8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 0 Now we can see that $i is an IV and it only has an IV section (and the corresponding flag). But be careful, you can taint this be using $i in a string context: perl -MDevel::Peek -E 'my $i = 0+!!0; "$i"; Dump $i' SV = PVIV(0x7fd841004e20) at 0x7fd841002eb8 REFCNT = 1 FLAGS = (IOK,POK,pIOK,pPOK) IV = 0 PV = 0x7fd84070b3f0 "0"\0 CUR = 1 LEN = 10 >From this we can see that using an IV in string context will cause perl to cache the string version of the IV. But note that, unlike PL_sv_no, the string value is actually "0" not "". This is mostly an issue for serialization (JSON in particular). Just for illustration of why the flags are important: perl -MDevel::Peek -E 'my $i = 0+!!0; Dump $i; "$i"; Dump $i; $i++; Dump $i' SV = IV(0x7f941402a0a8) at 0x7f941402a0b8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 0 SV = PVIV(0x7f941402c020) at 0x7f941402a0b8 REFCNT = 1 FLAGS = (IOK,POK,pIOK,pPOK) IV = 0 PV = 0x7f9413c04eb0 "0"\0 CUR = 1 LEN = 10 SV = PVIV(0x7f941402c020) at 0x7f941402a0b8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1 PV = 0x7f9413c04eb0 "0"\0 CUR = 1 LEN = 10 $i started off as an IV, but gets promoted to a PVIV by being used in string context. Then math is done on the IV portion which invalidates the cached string, so the POK flag is removed. The cached value of "0" is still present in the variable, but properly behaving code will not access it (only XS code could even see it). Just don't ask me about the pIOK, pNOK, and pPOK flags, 'cause I have never understood what they represent.