2010-04-08 13 views
6

Natknąłem się na sytuację (podczas rejestrowania różnych zmian danych), w której muszę określić, czy odwołanie ma prawidłowy wymuszenie ciągów (np. Można poprawnie wydrukować w dzienniku lub zapisać w bazie danych). Nie ma nic w Scalar::Util to zrobić, więc mam brukowanych razem coś przy użyciu innych metod w tej bibliotece:Jak określić, czy obiekt lub odwołanie ma poprawną metodę wymuszania?

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

Podejrzewam jednak, że może być lepszy sposób określania tego, sprawdzając wnętrzności zmienna w jakiś sposób. Jak można to zrobić lepiej?

Odpowiedz

6

Od perldoc overload:

overload::StrVal(arg)

Daje ciąg znaków arg jak w przypadku braku stringify przeciążeniem.

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

Zauważ, że overload::Method nie jest tu właściwe because:

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

Jeśli jeden lub dwa z tych operacji nie są przeciążone, można zamiast tego użyć pozostałych.

Dlatego sprawdzanie tylko w przypadku przeciążenia '""' spowoduje zwrócenie wyników fałszywie ujemnych w porównaniu z metodą wyświetlaną w pytaniu.

+0

Podobała mi się twoja starsza wersja lepiej, która pokazała, jak znaleźć metodę stringification - np. 'perl -MDateTime -Moverload -wle'my $ dt = DateTime-> now; my $ method = overload :: Method ($ dt, q {""}); print $ method -> ($ dt) '' :) – Ether

+0

@Ether Problem polega na tym, że 'bool' mógł zostać przeciążony, zapewniając stringyfikację bez przeciążania' '". –

Powiązane problemy