Perl-如何使用引用id?

Perl-如何使用引用id?,perl,Perl,打印对象时: my $hash = {}; print($hash); # it outputs some sort of hex identifier: HASH(0X3A8154) 如何将此十六进制标识符用作字符串或键 my $map = {}; my $object = {}; $map->{$object_id} = $object; # where $object_id is the string result of $object when printed 您得到的是引用的

打印对象时:

my $hash = {};
print($hash); # it outputs some sort of hex identifier: HASH(0X3A8154)
如何将此十六进制标识符用作字符串或键

my $map = {};
my $object = {};
$map->{$object_id} = $object; # where $object_id is the string result of $object when printed

您得到的是引用的字符串化†,在本例中是散列引用

因此,您可以获得所需的字符串并将其分配给变量(
my$id=“$hashref”

打印
哈希(0x2398d48)
两次

然后在具有哈希引用的示例中(“code>$object”–我将其称为
$hashref
),您可以执行以下操作

$map->{"$hashref"} = $hashref;
$map->{$hashref} = $hashref;
事实上你能做到

$map->{"$hashref"} = $hashref;
$map->{$hashref} = $hashref;
因为,
$hashref
被字符串化,以便获得键所需的字符串

然而,对于一般和通用用途来说,这似乎不是一个好主意。首先,如何区分各个
$hashref
的键(总是
HASH(num)
)?一个键用来识别与之相关的值,这里有一些“随机”数字

为什么不为您的对象提供有意义的id,并自行携带信息?您还可以使用直接包含
$hashref
s的数据结构,因为它们是标量。或者,更好的方法是编写一个类,使
$hashrefs
s是对象;然后可以设置所需的任何数据/属性

诚然,我不知道这如何适用于需要它的“分布式内存模型”,而且它肯定是用id明确标记引用的一种方法



†我在文档中找不到关于严格化的解释,因此无法提供链接。例如,请参见

如果要将引用的标识用作哈希键,正确的方法是使用:

如果知道对象不会使用运算符重载,则只需添加零即可:

$map->{0+$object} = $object;

哈希键必须始终为字符串。如果您提供一个引用或对象作为键,它将首先自动字符串化:
$hash{$x}
$hash{“$x”}
相同。默认情况下,字符串化对引用使用类似于
HASH(0x1234abc)
的格式,对对象使用类似于
SomeClass=HASH(0x1234abc)
的格式

您还可以强制引用一个数字,例如通过添加零。默认情况下,其计算结果为引用目标的内存地址/ID

my $ref = {};
my $obj = bless {} => 'SomeClass';

say sprintf "ref address: %x, stringify: %s", 0+$ref, "$ref";
say sprintf "obj address: %x, stringify: %s", 0+$obj, "$obj";
示例输出:

ref address: 1990178, stringify: HASH(0x1990178)
obj address: 19903d0, stringify: SomeClass=HASH(0x19903d0)
在对象重载字符串或数字运算符之前,此操作可以正常工作:

BEGIN {
  package Freaky;

  sub new {
    my ($class) = @_;
    return bless {} => $class;
  }

  use overload
    fallback => 1,
    q("") => sub { "custom stringification" },
    q(0+) => sub { 32 };
}

my $freaky = Freaky->new;
say sprintf "freaky address: %x, stringify: %s", 0+$freaky, "$freaky";
输出:

freaky address: 20, stringify: custom stringification
所以我们不能直接使用散列键这样的对象。但我们可以避开步骤过载

  • 要获取任何值的默认字符串化,请使用
    重载::StrVal()
    函数

  • 要获取任何引用的地址而不使用添加零等“技巧”,请使用
    Scalar::Util::refaddr()
    函数

示例输出:

freaky address: 2203178, stringify: Freaky=HASH(0x2203178)

您得到的是引用的字符串化(在本例中是hashref)。已经是字符串了。因此,您可以只指定使用
$object
作为散列键有什么问题吗?@SilvioMayolo您的意思是
$map->{$object}=$object使用字符串作为键,对象作为值?哈希键始终是标量,您所拥有的只是一个哈希引用,它也是标量。(对象将是实例化的类。)如果将哈希引用用作哈希键,它将被字符串化。@Matt Jacob谢谢,我以前没有意识到这一点。虽然我可以使用id->object map并生成自己的id,但我认为这种方法更简单。有什么特别的缺点吗?创建分布式内存模型的主要思想是,我需要一种远程引用对象的方法。@aoiee我现在想不出一个非常具体的问题。但是,您正在创建一个散列来跟踪
$object
s,那么为什么不提出一些包含更多信息或含义的分类(id)?通过这种方式,
$object
在某种意义上被映射到它自己。我担心如果一个“object”被赋予了一个函数或其他特殊情况,它将无法将一个id存储为属性。@aoiee,请稍候。您可以创建一些对象,使它们成为类的实际对象。然后您可以做各种事情来对它们进行编目/标识。我不明白“能够将id存储为属性”?首先,如果这是一个类,这正是您可以做的$对象\u id=\@数组将无法保存对象id属性。
freaky address: 2203178, stringify: Freaky=HASH(0x2203178)