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

.



Relevant Pages

  • Re: print sybase system stored procedure output to filehandle
    ... However there are tricks you can use in Perl to capture STDERR and/or ... STDOUT from subprocesses and black-box Perl subroutines. ... open STDERR, '>&', $log; ... helper process as soon as you open the filehandle and then wrote to the ...
    (comp.lang.perl.misc)
  • Re: prepend date to log
    ... STDERR "log message...";). ... what I'm not able to do is to automatically prepend the date to every ... entry in the debug log file (obviously without finding every print in ...
    (perl.beginners)
  • Can one use local to temporarily close STDERR?
    ... e.g. STDERR. ... Of course, I can achieve the desired effect (namely, selectively ... open STDERR, '>&', $save; ... In my address everything before the first period is backwards; ...
    (comp.lang.perl.misc)
  • Re: passing more than one file.
    ... loop through argv[] until you hit NULL. ... message to stderr and keep going. ... int main(int argc, char *argv) { ...
    (comp.lang.c)
  • Why TCP ECHO Not Work between distant Hosts?
    ... At a Server with IP 163.239.209.16, I typed, ... int main ... WSADATA wsaData; ... fputs(message, stderr); ...
    (microsoft.public.vc.mfc)