【问题标题】:use of perl's eq operator changes type of the arguments使用 perl 的 eq 运算符更改参数的类型
【发布时间】:2014-01-26 08:45:59
【问题描述】:

我制作了这个脚本来检查在意外使用“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

【问题讨论】:

  • 我不会说这个问题与 stackoverflow.com/a/12693984/223226 重复。当然,这个问题回答了我如何在不使用 to_json 的情况下查看类型,但我真正的问题是我的代码的结果是错误还是功能,例如为什么 eq 运算符会更改参数的类型。
  • Numeric 在 Perl 中不是一个类型,它是一个上下文。很可能 Perl 缓存并优先考虑与标量值关联的上下文数据(您可以使用Devel::Peek 获取有关标量发生的更多信息)。至于这里的基本原理/设计是什么,我不知道。部分是to_json 的一个特性,而不是 Perl - 它必须从它可以找到的任何东西中获取提示,如果一个标量被同时视为一个数字和一个字符串,它就会变得混乱(或安全地玩)跨度>

标签: perl perl-data-structures


【解决方案1】:

Perl 变量是多值的,例如它们有用于字符串、整数、浮点数和引用的插槽。

如果您将字符串分配给变量,它将存储在字符串槽中,并且该槽将被标记为有效。如果您稍后将变量作为数字访问,则字符串将被转换,浮点或整数槽将被更新并标记为有效。在您的示例中,$str 最初将具有一个有效的字符串槽,并且在与整数比较之后,它将 具有有效的整数槽。如果您将它与浮点数进行比较,它将有一个有效的浮点数插槽。您可以使用 Devel::Peek::Dump 进行检查:POK 表示有效的字符串槽,IOK 是有效的整数槽,NOK 是有效的浮点槽。

如果您存储一个整数然后将其用作字符串,也会发生类似的事情。在您的示例中,$num 最初将具有一个有效的整数槽(IOK),一旦您将其作为字符串(通过使用 eq)访问,它将被转换为字符串,并且字符串槽将被填充并有效(POK)另外到整数槽。

to_json 可能只是查看变量并获取它找到的第一个有效槽,从字符串开始(我猜这必须是 JSON::XS 中的 encode_sv - 这按以下顺序检查:字符串、浮点数、整数)。因此,如果字符串槽是有效的,它将被打印出来并在其周围加上引号。

其他语言(如 python)没有这种多槽的东西,它们只有一个类型,如果你在另一个上下文中使用变量,它会发牢骚。两种方式各有利弊:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 2015-03-27
    • 1970-01-01
    • 2013-12-25
    • 2023-01-24
    相关资源
    最近更新 更多