Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine if an object or reference has a valid string coercion?

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?

like image 271
Ether Avatar asked Apr 08 '10 18:04

Ether


1 Answers

From perldoc overload:

overload::StrVal(arg)

Gives string value of arg as in absence of stringify overloading.

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

Note that overload::Method is not appropriate here because:

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

If one or two of these operations are not overloaded, the remaining ones can be used instead.

Therefore, checking only if '""' is overloaded would return false negatives compared to the method you show in your question.

like image 53
Sinan Ünür Avatar answered Sep 22 '22 16:09

Sinan Ünür