I'm working with Marpa::R2, and am trying to catch errors using Try::Tiny. I am puzzled because when I put the parsing code into a try
block, the result of the value
method is undef
. Here's my code:
use strict;
use warnings;
use Marpa::R2;
use Data::Dumper;
use Try::Tiny;
my $grammar = Marpa::R2::Scanless::G->new(
{
source => \(<<'END_OF_SOURCE'),
:default ::= action => ::array
:discard ~ ws
ws ~ [\s]+
:start ::= Name
Name ::= Foo
Foo ~ [\w]+
END_OF_SOURCE
}
);
my $reader = Marpa::R2::Scanless::R->new(
{
grammar => $grammar,
}
);
my $input = 'foo';
try{
$reader->read(\$input);
}catch {
warn "caught error: $_";
}
my $value = $reader->value;
print Dumper $value;
I was going a little nuts trying to figure out what was the grammar, and then I realized that removing the try
block made the value of $reader->value
non-null. Even if I assign $value
within the try
block, it becomes undef
when the block is finished:
my $value;
try{
$reader->read(\$input);
$value = $reader->value;
}catch {
warn "caught error: $_";
}
print Dumper $value;
This seems to mean that if I want to catch errors with Try::Tiny
, I have to put ALL of my processing of $value
into the try
block, which is inconvenient.
Can anyone tell me what is causing this (I'd like an explanation of how this is possible in Perl)? And is there a way to fix it?
try{
$reader->read(\$input);
}catch {
warn "caught error: $_";
} <------ missing semicolon
my $value = $reader->value;
Keep in mind that try
is not actually a control structure. try
and catch
are simply subs with the &@
prototype. (I imagine that catch
returns some form of object.) As such, the above code is equivalent to
&try(sub { ... }, &catch(sub { ... }, my $value = $reader->value));
Notice how the assignment to $value
is being done before the try
?