perl 如何检查hashref是否是一个对象?

vngu2lb8  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(175)

我的Perl代码调用一个API,传递一个对字符串ID数组的引用,并期望返回一个对象数组。

my @customers = $api->get_customer_details(\@customer_ids);

for my $customer (@customers) {

   # debug
   print $customer . "/n";
   print ref($customer) . "/n";
   print Dumper ($customer);

   if (!$customer) {
      print "No customer object\n";
      # do stuff
      last;
   }
   
   print "Got the customer object\n";
   $info->{customer_objects}{$customer->customer_id} = $customer;
}

在99%的情况下,当我运行这个程序时,我会得到客户对象。但是,我偶尔会得到输出:

HASH(0x12345)
HASH
{}
Got the customer object
Can't call method "customer_id" on unblessed reference at ..

我试图编辑我的IF语句来检查空的hashref,但是它总是忽略IF

if (!$customer || !%$customer)

当我通过命令行进行测试时,空的hashref按预期工作:

$ perl -E 'my $hr = {};  if (!$hr || !%$hr) { say "empty" } else { "nonempty" }'

empty

我不明白问题出在哪里。看起来我的调试输出不准确,而且我实际上没有得到一个空的hashref。有人能解释一下这是怎么回事吗?我怎么可能知道$customer是什么,以及如何在我的IF语句中忽略这种情况?

toe95027

toe950271#

您可以检查blessed,如问题注解中所示。
但是,看起来您可能会遇到一些情况,您查询了特定的ID,但没有该ID的记录。可能情况并非如此,因此如果它甚至不接近原因,则忽略此问题。
在这种情况下,您可能会得到一些不是客户对象的东西(因为没有客户)。我宁愿降低复杂性,这样应用程序就不必考虑它,我就可以更快地捕获它。
这项工作可能发生在get_customer_details中。
接下来的技巧是找出如何表示不存在的客户。一种方法是简单地让get_customer_details不为不存在的ID返回任何内容。返回的列表中不包含这些条目。这样以后的方法调用就不会有问题。但是,您会遇到静默失败,并且您可以获得比您提供的参数更少的条目。
另一种方法是在列表中返回undef,然后查找定义的值。undef位置将与@customer_ids中的坏客户ID相关联,您可以处理这个问题。

my @customers = $api->get_customer_details(\@customer_ids);

for( my $i = 0; $i < @customers; $i++ ) {
    unless( defined $customers[$i] ) {
        warn "No customer for $customer_ids[$i]";
        next;
        }
    ...
    }

但是我倾向于有一个类似于null customer的并行对象。它可以告诉您没有customer,ID是什么,等等。它可能响应所有正常的customer方法,但是警告并返回undef。可能有一些方法可以告诉你哪些对象是真实的的客户,比如exists(或者更好的名字):

my @customers = $api->get_customer_details(\@customer_ids);

foreach my $customer ( @customers ) {
    unless( $customers->exists ) {
        # this would be a Customer::Null or something
        # that responds to the same methods
        warn "No customer for " . $customer->id";
        next;
        }
    
    ...
    }

我认为最后一种方法是因为当这些对象通过程序时,它们携带着它们创建的故事。这些东西甚至可以存储API数据结构的一部分,这样你就可以看到发生了什么。也许有一个客户,但无论是什么把它变成了客户,都不了解它。

相关问题