如何解决以下问题?
use 5.014;
use warnings;
use Test::Simple tests => 4;
ok( doit(0123) == 83, "arg as octal number" );
ok( doit(83) == 83, "arg as decimal number" );
ok( doit('0123') == 83, "arg as string with leading zero" );
ok( doit('123') == 83, "arg as string without leading zero" );
sub doit {
my $x = shift;
return $x; # how to replace this line
#return got_the_arg_as_string ? oct($x) : $x; # with something like this
}
E.g。如果我传递给doit
子字符串 - 均值引用值 - (有或没有前导零),它应该转换为八进制值。否则,它只是一个数字。
答案 0 :(得分:6)
Perl的标量内部表示可以是整数或字符串,并且随时可以将该表示强制转换为任何其他标量类型。使用C / XS代码可以获得标量的内部类型。例如,JSON::XS
模块执行此操作来确定值是应该呈现为数字还是呈现为字符串。
以下是您的问题的概念证明:
use Inline 'C';
sub foo {
my ($x) = @_;
print $x, " => isString: ", isString($x), "\n";
}
foo(0123);
foo('0123');
__END__
int isString(SV* sv)
{
return SvPOK(sv) ? 1 : 0;
}
节目输出:
83 => isString: 0
0123 => isString: 1
相关帖子:
Difference between $var = 500 and $var = '500'
When does the difference between a string and a number matter in Perl 5?
Why does the JSON module quote some numbers but not others?
更新部分此功能在核心B
模块中公开,因此无需添加为XS依赖项:
use B;
sub isString {
my $scalar = shift;
return 0 != (B::svref_2object(\$scalar)->FLAGS & B::SVf_POK)
}