Identify if a scalar is int, double or text



Hello,

I have a list of 4 scalars
my @L = (3, '3', 3.0, '3.0');

The first is obviously an int, the second is text, the third a double
and the last is text again.

I want to write a subroutine type_id which returns either 'int',
'double', 'text' (or '?') for each of the scalars, so that

print type_id($_), ' ' for (@L); print "\n";

results in the following output:

int text double text

I have found a solution where I use Devel::Peek, call Dump(), redirect
STDERR into an "in-memory" file ( \$data ) and analyse the "in-memory"
content:

$data =~ /^SV = IV(0x/ # for ints
$data =~ /^SV = NV(0x/ # for doubles
$data =~ /^SV = PV(0x/ # for text

but I wanted to know whether there is a better way.

**********************************************************
Here is my solution:

use strict;
use warnings;

use Devel::Peek;

print STDERR "Beginning of program\n";

my @L = (3, '3', 3.0, '3.0');

print type_id($_), ' ' for (@L);
print "\n";

print STDERR "End of program\n";

sub type_id {

# ============================
# At first I could not get the "in-memory"
# working. It took me a while before I
# found the all important documentation
# in perldoc -f open:
#
# [...] if you try to re-open STDOUT or
# STDERR as an "in memory" file, you have
# to close it first [...]
#
# As a consequence, a simple
# local *STDERR;
# open STDERR, '>', \$data;
# does not work.
#
# The following redirects STDERR into an
# "in-memory" file, but leaves STDERR
# closed on exit:
# local *STDERR = *STDERR;
# close STDERR;
# open STDERR, '>', \$data;
#
# so we have to dup STDERR first and
# restore STDERR manually at the end
# (...knowing that if the restore fails,
# we won't have STDERR anymore):
# ============================

# dup STDERR
open my $olderr, '>&', \*STDERR
or return "?002 [dup STDERR: $!]";
close STDERR
or return "?005 [close STDERR: $!]";

my $data = '';
open STDERR, '>', \$data;
Dump $_[0];
close STDERR;

# restore STDERR
open STDERR, '>&', $olderr or die;

if ($data =~ m{^SV = (.V)}) {
if ($1 eq 'IV') { return 'int' }
if ($1 eq 'NV') { return 'double' }
if ($1 eq 'PV') { return 'text' }
return "?020 [Invalid: SV = $1]";
}
return "?030 [Err: ".substr($data, 0, 12)."]";
}

--
Klaus

.