1

I have a program which accepts a perl data structure which is intended to be a Storable scalar. Is there a way to test if the scalar is a valid Storable object, without dying if it isn't?

For instance, if I do:

use Storable qw(freeze thaw);
my $ref = thaw("lol_not_storable")

I get back "Storable binary image v54.111 more recent than I am (v2.8) at /usr/local/lib/perl/5.12.4/Storable.pm line 420, at test.pl line 5"

I would like to figure out if it is possible to cleanly handle these exceptions without eval. Is it possible without rewriting the Storable Perl Module?

GoldenNewby
  • 4,382
  • 8
  • 33
  • 44
  • 6
    What do you have against `eval`? (Or one of its wrappers, like [Try::Tiny](http://search.cpan.org/perldoc?Try::Tiny)? – cjm Mar 16 '12 at 09:22
  • [»You can't do it without checking. The most simple approach is to just do the decoding and then handle the exception.«](http://stackoverflow.com/a/2583981/46395) – daxim Mar 16 '12 at 10:27
  • @cjm Nothing really, but I was already aware of how to catch this error with eval. The documentation has a section for "Error Reporting" http://perldoc.perl.org/Storable.html, I was hoping for a solution that would use it. I wasn't able to get it to work myself. – GoldenNewby Mar 17 '12 at 00:37

2 Answers2

3
eval { thaw("lol_not_storable"); };

is not the same thing as

eval qq/thaw("lol_not_storable");/;

in that Perl has ample chance to parse the first, but waits to parse the second. Observe, the below is a compile error:

use 5.014;
use strict;
use warnings;

say 'Would print without compile error';
eval { $i++; };
^D

Global symbol "$i" requires explicit package name at - line 8.
Execution of - aborted due to compilation errors.

Whereas eval '$i++' wouldn't be. I think most of the discouragement you have heard about eval is more of the latter type and not of the former. The latter evaluates a string as code, the former mainly tells Perl "don't die."

Here's the string version:

use 5.014;
use strict;
use warnings;

say 'Would print without compile error';
eval ' $i++;';

Outputs:

Would print without compile error

The code still fails to compile, but only when it's eval-ed, and only has effect when I check $@, which reads:

$@= 'Global symbol "$i" requires explicit package name at (eval 24) line 1.
'
Axeman
  • 29,660
  • 2
  • 47
  • 102
0

Do it with magic :)

use Data::Dumper;
use Storable qw(freeze thaw read_magic);

my $storable_str = freeze( [ 1 .. 42 ] );
print Dumper( read_magic($storable_str) );
# prints:
# $VAR1 = {
#     'netorder'   => 0,
#     'hdrsize'    => 15,
#     'version'    => '2.7',
#     'minor'      => 7,
#     'longsize'   => 8,
#     'ptrsize'    => 8,
#     'version_nv' => '2.007',
#     'byteorder'  => '12345678',
#     'major'      => 2,
#     'intsize'    => 4,
#     'nvsize'     => 8
# };

my $ordinary_str = join( ',', (1 .. 42) );
print Dumper( read_magic($ordinary_str) );
# prints:
# $VAR1 = undef;

# So:
if(read_magic($something_to_check)){
    my $ref = thaw($something_to_check);
}else{
    # foo
}