2012-03-20 14 views
5

Piszę coś, aby uzyskać coś podobnego do JSON, ze struktury Perla. Chcę, powołując się zachowywać tak:Czy istnieje sposób na sprawdzenie, czy skalar został usztywniony, czy nie?

"string" outputs "string" 
"05" outputs "05" 
"5" outputs "5" 
5 outputs 5 
05 outputs 5, or 05 would be acceptable 

JSON :: XS obsługuje to poprzez badanie, czy została skalarne „stringified”, czy nie, co moim zdaniem jest bardzo fajne. Ale nie mogę znaleźć sposobu na zrobienie tego testu samemu bez pisania XS, którego wolałbym uniknąć. czy to możliwe? Nie mogę tego znaleźć nigdzie na CPAN bez znalezienia ogromnej pedantry o Scalar :: Util :: looks_like_number, itp., Który zupełnie nie jest tym, czego chcę. Jedynym ograniczeniem, jakie mogę znaleźć, jest Devel :: Peek, który czuje się źle. A także, podobnie jak JSON :: XS, jestem zadowolony z tego secenario:

my $a = 5; 
print $a."\n"; 
# now $a outputs "5" instead of 5) 

Odpowiedz

5

Sprawdzić wyjście B::svref_2object:

use B; 
($x, $y, $z) = ("5", 5, 5.0); 

print ref(B::svref_2object(\$x)), "\n"; 
print ref(B::svref_2object(\$y)), "\n"; 
print ref(B::svref_2object(\$z)), "\n"; 

wyjściowa:

B::PV 
B::IV 
B::NV 

Albo, jak sugeruje Ikegami, jeśli wolisz odnośnika pPOK flag

if (B::svref_2object(\$x)->FLAGS & B::SVp_POK) { 
    print "I guess \$x is stringy\n"; 
} 
+0

Nie ma to nic wspólnego z typem SV. Ma to związek z flagą pPOK. – ikegami

+0

Na przykład spójrz na 'my $ x =" "; x = 5; my $ y = 5; "". $ y; '. Oba są PVIV, ale tylko jeden jest "żylasty". – ikegami

+0

Właśnie to zauważyłem. Byłoby miło, gdyby B rzeczywiście wymienił to, co dostarczył! Niestety wydaje się, że 'SvGETMAGIC' jest niedostępny. – ikegami

2

Prawdopodobnie nie jest to najlepszy sposób, ale jeśli JSON robi to, co chcesz, to dlaczego nie korzystać?

sub is_stringy { 
    encode_json([$_[0]]) =~ /["']/ 
} 

is_stringy(5);  # undef 
is_string("5");  # 1 
+0

Prawdopodobnie to zrobię, jeśli nie znajdę lepszej odpowiedzi. To jednak wydaje się nie do zniesienia. Po prostu zachowałbym wynik skalarny JSON :: XS, ale niestety to, co wyprowadzam, nie jest JSON i ma różne reguły ucieczki itp. – Yobert

4

Można zrobić tak wiele już nie wydaje się, aby zostały stringified stosując następujący:

$x = 0+$x; 

Na przykład

$ perl -MJSON::XS -E' 
    $_ = 4; 
    say encode_json([$_]); # [4] 
    "".$_; 
    say encode_json([$_]); # ["4"] 
    $_ = 0 + $_; 
    say encode_json([$_]); # [4] 
' 

Wykrywanie czy coś zostało stringified jest trudniejsze, ponieważ JSON :: XS patrzy na elementy wewnętrzne Perla. Można użyć następujących:

sub is_stringy { 
    { no warnings 'void'; "".$_[0]; } 
    return 1; 
} 

ale nie sądzę, że to, co chcesz :) Nie wiem jak wykryć „korupcję” bez pisania kodu XS. To, co chcesz wiedzieć, to czy SvPOKp jest prawdziwe dla skalaru (po wywołaniu SvGETMAGIC na skalarnym).

use Inline C => <<'__EOI__'; 

    SV* is_stringy(SV* sv) { 
     SvGETMAGIC(sv); 
     return SvPOKp(sv) ? &PL_sv_yes : &PL_sv_no; 
    } 

__EOI__ 

$_ = 4; 
say is_stringy($_) ?1:0; # 0 
{ no warnings 'void'; "".$_; } 
say is_stringy($_) ?1:0; # 1 
$_ = 0+$_; 
say is_stringy($_) ?1:0; # 0 

oo! Okazuje się, że B ma zapewnić SVp_POK, więc można (prawie) być wykonane w formie pisemnej bez nowy kod XS

use B qw(svref_2object SVp_POK); 

sub is_stringy { 
    my ($s) = @_; 
    my $sv = svref_2object(\$s); 
    #$sv->GETMAGIC(); # Not available 
    return $sv->FLAGS & SVp_POK; 
} 

Będąc w stanie wywołać SvGETMAGIC ma wady, ale to będzie działać prawie cały czas.

+0

@Yobert, zaktualizowany, ponownie. – ikegami

Powiązane problemy