cajwine cajwine - 5 months ago 6x
Perl Question

Differentiate string and number argument in perl

How to solve the following?

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. If i pass to the
sub any string - mean quoted value - (with or without the leading zero), it should be converted to octal value. Otherwise, it is just an number.


It is just an minimal verifiable example :).

In the background of the question are the "file permission bits" and "web-forms" and verification.

E.g. when I got entered into the web-form the value
- without leading zero - it should be converted to the octal number. (aka I treating any value from the form as

But the
funtion really should be usable with unquoted args too, e.g.


Of course, it is solvable with one more exact step (e.g. when the value comes from the web-form, convert the value to octal), I just wondering about the most simple solution.

mob mob

Perl's internal representation of a scalar may be as in integer or a string, and it remains ready to coerce that representation into any other scalar type at any moment. It is possible with C/XS code to get at a scalar's internal type. The JSON::XS module does this, for example, to decide whether a value should be rendered as a number or as a string.

Here's a proof of concept for your problem:

use Inline 'C';
sub foo {
    my ($x) = @_;
    print $x, " => isString: ", isString($x), "\n";

int isString(SV* sv)
    return SvPOK(sv) ? 1 : 0;

Program output:

83 => isString: 0
0123 => isString: 1

Related posts:

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?

Update some of this functionality is exposed in the core B module, so no need to add as XS dependency:

use B;
sub isString {
    my $scalar = shift;
    return 0 != (B::svref_2object(\$scalar)->FLAGS & 1024)