6

I've run into a situation (while logging various data changes) where I need to determine if a reference has a valid string coercion (e.g. can properly be printed into a log or stored in a database). There isn't anything in Scalar::Util to do this, so I have cobbled together something using other methods in that library:

use strict;
use warnings;

use Scalar::Util qw(reftype refaddr);

sub has_string_coercion
{
    my $value = shift;

    my $as_string = "$value";
    my $ref = ref $value;
    my $reftype = reftype $value;
    my $refaddr = sprintf "0x%x", refaddr $value;

    if ($ref eq $reftype)
    {
        # base-type references stringify as REF(0xADDR)
        return $as_string !~ /^${ref}\(${refaddr}\)$/;
    }
    else
    {
        # blessed objects stringify as REF=REFTYPE(0xADDR)
        return $as_string !~ /^${ref}=${reftype}\(${refaddr}\)$/;
    }
}

# Example:
use DateTime;
my $ref1 = DateTime->now;
my $ref2 = \'foo';

print "DateTime has coercion: " . has_string_coercion($ref1) . "\n\n";
print "scalar ref has coercion: " . has_string_coercion($ref2) . "\n";

However, I suspect there might be a better way of determining this by inspecting the guts of the variable in some way. How can this be done better?

4

1 回答 1

6

perldoc 重载

overload::StrVal(arg)

arg 在没有 stringify 重载的情况下给出 as 的字符串值。

sub can_stringify {
    my ($obj) = @_;
    return "$obj" ne overload::StrVal($obj);
}

请注意,overload::Method这里不合适,因为

  1. 'bool', '""', '0+',

如果这些操作中的一个或两个没有重载,则可以使用剩余的操作来代替。

因此,'""'与您在问题中显示的方法相比,仅检查是否重载会返回假阴性。

于 2010-04-08T18:09:41.823 回答