我制作了这个脚本来检查标记在意外使用'eq'而不是'=='时如何变化,反之亦然。在字符串上使用'=='只会改变,但在数字上使用'eq'会以某种方式改变标量。代码如下:
#!/usr/bin/perl
use strict;
use JSON;
my $str = "123";
my $num = 123;
print "BEFORE:\n";
print "str: ", \$str, " num: ", \$num, "\n";
print to_json({str => $str, num => $num}, {pretty => 1});
if ($str == 23) { }
if ($num eq "123") { }
print "AFTER:\n";
print "str: ", \$str, " num: ", \$num, "\n";
print to_json({str => $str, num => $num}, {pretty => 1});
print "\n";
输出:
BEFORE:
str: SCALAR(0x8010f8) num: SCALAR(0x801050)
{
"num" : 123,
"str" : "123"
}
AFTER:
str: SCALAR(0x8010f8) num: SCALAR(0x801050)
{
"num" : "123",
"str" : "123"
}
使用单词,$ num从数字变为字符串。通过评论该行
if ($num eq "123") { }
$ num不再更改。这是一个错误或功能吗?为什么会这样?另外,如何在不使用to_json的情况下看到这个?
perl --version
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
答案 0 :(得分:6)
Perl变量是多值的,例如它们有字符串,整数,浮点和引用的插槽。
如果为变量分配字符串,它将存储在字符串插槽中,此插槽将标记为有效。如果稍后以变量形式访问变量,则将转换该字符串,并更新浮点或整数槽并标记为有效。在您的示例中,$ str最初将具有有效的字符串槽,并且在与整数进行比较之后,还具有有效的整数槽。如果您将它与浮点数进行比较,则会有一个有效的浮动槽。您可以使用Devel :: Peek :: Dump来检查:POK表示有效的字符串槽,IOK是有效的整数槽,NOK是有效的浮动槽。
类似的事情发生,如果你存储一个整数,然后将其用作字符串。在你的例子中,$ num最初将有一个有效的整数槽(IOK),一旦你以字符串形式访问它(通过使用eq),它将被转换为字符串,字符串槽将被填充并且有效(POK)另外到整数槽。
to_json可能只是查看变量并获取它找到的第一个有效插槽,从字符串开始(我想这必须是JSON :: XS中的encode_sv - 这将按以下顺序检查:string,float,integer)。因此,如果字符串插槽有效,它将在其周围打印引号。
其他语言(比如python)没有这个多槽的东西,它们只有一个类型,如果你在另一个上下文中使用变量,它会呱呱叫。两种方式各有利弊:)