2010-04-08 15 views
6

He encontrado una situación (al registrar varios cambios de datos) donde necesito determinar si una referencia tiene una coerción de cadena válida (por ejemplo, puede imprimirse correctamente en un registro o almacenarse en una base de datos). No hay nada en Scalar::Util para hacer esto, así que he improvisado algo utilizando otros métodos en esa biblioteca:¿Cómo puedo determinar si un objeto o referencia tiene una coerción de cadena válida?

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"; 

Sin embargo, sospecho que podría ser una mejor manera de determinar esto mediante la inspección de las entrañas de la variable de alguna manera. ¿Cómo se puede hacer esto mejor?

Respuesta

6

De perldoc overload:

overload::StrVal(arg)

Da valor de cadena de arg como en ausencia de sobrecarga stringify.

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

Tenga en cuenta que overload::Method no es apropiado en este caso because:

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

Si uno o dos de estas operaciones no están sobrecargados, el los restantes se pueden usar en su lugar.

Por lo tanto, comprobar si '""' está sobrecargado devolverá falsos negativos en comparación con el método que muestra en su pregunta.

+0

Me gustó más su versión anterior, que mostró cómo encontrar el método de stringification - por ej. 'perl -MDateTime -Moverload -wle'my $ dt = DateTime-> now; my $ method = overload :: Method ($ dt, q {""}); print $ method -> ($ dt) '':) – Ether

+0

@Ether El problema es que' bool' podría haberse sobrecargado, proporcionando una cadena sin '' '' '' estar sobrecargado. –

Cuestiones relacionadas