Mailing List Archive

New function suggestion: eval-or-die
I have a few bits of code in unit tests of some new syntax that might
not even be valid perl, depending on the build). Therefore it -has- to
be a string eval.

SKIP: {
skip "No PL_infix_plugin", 1 unless XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;

# Need to string-eval because this won't even compile on older perls
my $result = eval '10 add 20';
is( $result, 30, 'add infix operator' );
}

Annoyingly, this eval() silently accepts syntax errors or runtime
exceptions, turning them into a simple undef; that unless I remember to
look in $@, gets lost.

To solve this I wrote a little(!) helper function:

sub evalordie
{
my ( $code ) = @_;
my @result = ("notset");

my $ok = defined eval (
wantarray ? "do { \@result = $code }; 1" :
defined wantarray ? "do { \$result[0] = $code }; 1 " :
"do { $code }; 1" );
$ok or die $@;

return @result if wantarray;
return $result[0];
}

The implementation of that is somewhat annoying as it tries to remain
context-transparent.

I feel it would be nice to provide a function of this behaviour in the
new "builtins" space at some point. Needs a better name though -
suggestions welcome.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: New function suggestion: eval-or-die [ In reply to ]
> Needs a better name though -
suggestions welcome.

edie, seval (strict eval), decide, assess

I like decide

:-)

On Mon, Sep 13, 2021 at 1:03 PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> I have a few bits of code in unit tests of some new syntax that might
> not even be valid perl, depending on the build). Therefore it -has- to
> be a string eval.
>
> SKIP: {
> skip "No PL_infix_plugin", 1 unless
> XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
>
> # Need to string-eval because this won't even compile on older perls
> my $result = eval '10 add 20';
> is( $result, 30, 'add infix operator' );
> }
>
> Annoyingly, this eval() silently accepts syntax errors or runtime
> exceptions, turning them into a simple undef; that unless I remember to
> look in $@, gets lost.
>
> To solve this I wrote a little(!) helper function:
>
> sub evalordie
> {
> my ( $code ) = @_;
> my @result = ("notset");
>
> my $ok = defined eval (
> wantarray ? "do { \@result = $code }; 1" :
> defined wantarray ? "do { \$result[0] = $code }; 1 " :
> "do { $code }; 1" );
> $ok or die $@;
>
> return @result if wantarray;
> return $result[0];
> }
>
> The implementation of that is somewhat annoying as it tries to remain
> context-transparent.
>
> I feel it would be nice to provide a function of this behaviour in the
> new "builtins" space at some point. Needs a better name though -
> suggestions welcome.
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
>
Re: New function suggestion: eval-or-die [ In reply to ]
Wouldn't it be better to add support for the eval(STRING) builtin to autodie?
Generally I think perl should adopt autodie or something similar as part of core.
That would be better than a special-case "or die" builtin just for string eval.


This email and any files transmitted with it are CONFIDENTIAL and are intended solely for the use of the individual(s) or entity to whom they are addressed. Any unauthorised copying, disclosure or distribution of the material within this email is strictly forbidden. Any views or opinions presented within this email are solely those of the author and do not necessarily represent those of PGIM Limited, QMA Wadhwani LLP or their affiliates unless otherwise specifically stated. An electronic message is not binding on its sender. Any message referring to a binding agreement must be confirmed in writing and duly signed. If you have received this email in error, please notify the sender immediately and delete the original. Telephone, electronic and other communications and conversations with PGIM Limited, QMA Wadhwani LLP and/or their associated persons may be recorded and retained. PGIM Limited and QMA Wadhwani LLP are authorised and regulated by the Financial Conduct Authority. PGIM Limited (registered in England No. 3809039) has its registered office at Grand Buildings, 1-3 Strand, Trafalgar Square, London WC2N 5HR and QMA Wadhwani LLP (registered in England No. OC303168) has its registered office at 9th Floor, Orion House, 5 Upper St. Martin's Lane, London, England, WC2H 9EA.

Please note that your personal information may be stored and processed in any country where we have facilities or in which we engage service providers. If you provide personal information to us by email or otherwise, you consent to the transfer of that information to countries outside of your country of residence and these countries may have different data protection rules than your country.

To learn about our privacy policies, please use this link<https://www.pgim.com/disclaimer/privacy-center> to read the Privacy Notices.
Re: New function suggestion: eval-or-die [ In reply to ]
On Mon, Sep 13, 2021 at 5:03 AM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> I have a few bits of code in unit tests of some new syntax that might
> not even be valid perl, depending on the build). Therefore it -has- to
> be a string eval.
>
> SKIP: {
> skip "No PL_infix_plugin", 1 unless
> XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
>
> # Need to string-eval because this won't even compile on older perls
> my $result = eval '10 add 20';
> is( $result, 30, 'add infix operator' );
> }
>
> Annoyingly, this eval() silently accepts syntax errors or runtime
> exceptions, turning them into a simple undef; that unless I remember to
> look in $@, gets lost.
>
> To solve this I wrote a little(!) helper function:
>
> sub evalordie
> {
> my ( $code ) = @_;
> my @result = ("notset");
>
> my $ok = defined eval (
> wantarray ? "do { \@result = $code }; 1" :
> defined wantarray ? "do { \$result[0] = $code }; 1 " :
> "do { $code }; 1" );
> $ok or die $@;
>
> return @result if wantarray;
> return $result[0];
> }
>
> The implementation of that is somewhat annoying as it tries to remain
> context-transparent.
>
> I feel it would be nice to provide a function of this behaviour in the
> new "builtins" space at some point. Needs a better name though -
> suggestions welcome.
>

It would be analogous to do BLOCK, but unfortunately do STRING is taken...

-Dan
Re: New function suggestion: eval-or-die [ In reply to ]
On Tue, Sep 14, 2021 at 12:36 AM Ed Avis <ed.avis@qmaw.com> wrote:

> Wouldn't it be better to add support for the eval(STRING) builtin to
> autodie?
> Generally I think perl should adopt autodie or something similar as part
> of core.
> That would be better than a special-case "or die" builtin just for string
> eval.
>

That wouldn't be appropriate. The purpose of the eval function is to trap
exceptions.

-Dan
Re: New function suggestion: eval-or-die [ In reply to ]
On Mon, Sep 13, 2021 at 10:03:02AM +0100, Paul LeoNerd Evans wrote:

> I have a few bits of code in unit tests of some new syntax that might
> not even be valid perl, depending on the build). Therefore it -has- to
> be a string eval.
>
> SKIP: {
> skip "No PL_infix_plugin", 1 unless XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
>
> # Need to string-eval because this won't even compile on older perls
> my $result = eval '10 add 20';
> is( $result, 30, 'add infix operator' );
> }
>
> Annoyingly, this eval() silently accepts syntax errors or runtime
> exceptions, turning them into a simple undef; that unless I remember to
> look in $@, gets lost.
>
> To solve this I wrote a little(!) helper function:
>
> sub evalordie
> {
> my ( $code ) = @_;
> my @result = ("notset");
>
> my $ok = defined eval (
> wantarray ? "do { \@result = $code }; 1" :
> defined wantarray ? "do { \$result[0] = $code }; 1 " :
> "do { $code }; 1" );
> $ok or die $@;
>
> return @result if wantarray;
> return $result[0];
> }
>
> I feel it would be nice to provide a function of this behaviour in the
> new "builtins" space at some point. Needs a better name though -
> suggestions welcome.

The obvious problem is that your new syntax might legitimately evaluate
to C<undef> in a perl that supports it.

--
David Cantrell | Minister for Arbitrary Justice

"IMO, the primary historical significance of Unix is that it marks the
time in computer history where CPUs became so cheap that it was possible
to build an operating system without adult supervision."
-- Russ Holsclaw in a.f.c
Re: New function suggestion: eval-or-die [ In reply to ]
On Tue, Sep 14, 2021 at 6:37 AM David Cantrell <david@cantrell.org.uk>
wrote:

> On Mon, Sep 13, 2021 at 10:03:02AM +0100, Paul LeoNerd Evans wrote:
>
> > I have a few bits of code in unit tests of some new syntax that might
> > not even be valid perl, depending on the build). Therefore it -has- to
> > be a string eval.
> >
> > SKIP: {
> > skip "No PL_infix_plugin", 1 unless
> XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
> >
> > # Need to string-eval because this won't even compile on older perls
> > my $result = eval '10 add 20';
> > is( $result, 30, 'add infix operator' );
> > }
> >
> > Annoyingly, this eval() silently accepts syntax errors or runtime
> > exceptions, turning them into a simple undef; that unless I remember to
> > look in $@, gets lost.
> >
> > To solve this I wrote a little(!) helper function:
> >
> > sub evalordie
> > {
> > my ( $code ) = @_;
> > my @result = ("notset");
> >
> > my $ok = defined eval (
> > wantarray ? "do { \@result = $code }; 1" :
> > defined wantarray ? "do { \$result[0] = $code }; 1 " :
> > "do { $code }; 1" );
> > $ok or die $@;
> >
> > return @result if wantarray;
> > return $result[0];
> > }
> >
> > I feel it would be nice to provide a function of this behaviour in the
> > new "builtins" space at some point. Needs a better name though -
> > suggestions welcome.
>
> The obvious problem is that your new syntax might legitimately evaluate
> to C<undef> in a perl that supports it.


This is allowed and part of the point. The pseudocode returns 1 from the
evals to distinguish it from the error case, and a builtin would similarly
not be result-dependent.

-Dan
Re: New function suggestion: eval-or-die [ In reply to ]
On Mon, 13 Sept 2021 at 11:03, Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> I have a few bits of code in unit tests of some new syntax that might
> not even be valid perl, depending on the build). Therefore it -has- to
> be a string eval.
>
> SKIP: {
> skip "No PL_infix_plugin", 1 unless
> XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
>
> # Need to string-eval because this won't even compile on older perls
> my $result = eval '10 add 20';
> is( $result, 30, 'add infix operator' );
> }
>
> Annoyingly, this eval() silently accepts syntax errors or runtime
> exceptions, turning them into a simple undef; that unless I remember to
> look in $@, gets lost.
>
> To solve this I wrote a little(!) helper function:
>
> sub evalordie
> {
> my ( $code ) = @_;
> my @result = ("notset");
>
> my $ok = defined eval (
> wantarray ? "do { \@result = $code }; 1" :
> defined wantarray ? "do { \$result[0] = $code }; 1 " :
> "do { $code }; 1" );
> $ok or die $@;
>
> return @result if wantarray;
> return $result[0];
> }
>
> The implementation of that is somewhat annoying as it tries to remain
> context-transparent.
>
> I feel it would be nice to provide a function of this behaviour in the
> new "builtins" space at some point. Needs a better name though -
> suggestions welcome.
>

Personally i feel like this is not really suitable for builtin's, I also
think it kinda solves the wrong part of the problem.

It feels to me like what you want is to distinguish "not compilable" from
"executes and returns undef", which currently you cant distinguish without
the kind of tricks you outline here.

Another approach would be to do something like this:

my $code= eval "sub { $code }";
if ($code) {
my $answer= $code->();
}

Which then suggests it would be nice if we provided decomposed versions of
eval in builtin.

Eg, it would be nice if I could do:

my $compiled= builtin::compile("10 add 22");
builtin::execute($compiled, $error_handler); # eg execute $compiled->() and
if an error happens call $error_handler->($@);

I think Zefram did something like this already and put it on CPAN.

Anyway, my point here is I dont think this wrapper around eval is that
helpful outside of the special case you are talking about, but a decomposed
eval function would be useful in many cases.

I mean, I recognize the problem, we train all our devs to ALWAYS do eval
like you show here pretty much, but I think there is a better solution than
the one you are proposing, especially if it is to go into builtin.

cheers,
Yves


--
perl -Mre=debug -e "/just|another|perl|hacker/"
Re: New function suggestion: eval-or-die [ In reply to ]
On Wed, 15 Sept 2021 at 10:34, demerphq <demerphq@gmail.com> wrote:

> On Mon, 13 Sept 2021 at 11:03, Paul "LeoNerd" Evans <
> leonerd@leonerd.org.uk> wrote:
>
>> I have a few bits of code in unit tests of some new syntax that might
>> not even be valid perl, depending on the build). Therefore it -has- to
>> be a string eval.
>>
>> SKIP: {
>> skip "No PL_infix_plugin", 1 unless
>> XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN;
>>
>> # Need to string-eval because this won't even compile on older perls
>> my $result = eval '10 add 20';
>> is( $result, 30, 'add infix operator' );
>> }
>>
>> Annoyingly, this eval() silently accepts syntax errors or runtime
>> exceptions, turning them into a simple undef; that unless I remember to
>> look in $@, gets lost.
>>
>> To solve this I wrote a little(!) helper function:
>>
>> sub evalordie
>> {
>> my ( $code ) = @_;
>> my @result = ("notset");
>>
>> my $ok = defined eval (
>> wantarray ? "do { \@result = $code }; 1" :
>> defined wantarray ? "do { \$result[0] = $code }; 1 " :
>> "do { $code }; 1" );
>> $ok or die $@;
>>
>> return @result if wantarray;
>> return $result[0];
>> }
>>
>> The implementation of that is somewhat annoying as it tries to remain
>> context-transparent.
>>
>> I feel it would be nice to provide a function of this behaviour in the
>> new "builtins" space at some point. Needs a better name though -
>> suggestions welcome.
>>
>
> Personally i feel like this is not really suitable for builtin's, I also
> think it kinda solves the wrong part of the problem.
>
> It feels to me like what you want is to distinguish "not compilable" from
> "executes and returns undef", which currently you cant distinguish without
> the kind of tricks you outline here.
>
> Another approach would be to do something like this:
>
> my $code= eval "sub { $code }";
> if ($code) {
> my $answer= $code->();
> }
>
> Which then suggests it would be nice if we provided decomposed versions of
> eval in builtin.
>
> Eg, it would be nice if I could do:
>
> my $compiled= builtin::compile("10 add 22");
> builtin::execute($compiled, $error_handler); # eg execute $compiled->()
> and if an error happens call $error_handler->($@);
>

And for your use case you wouldnt use builtin::execute(), you just do
$compiled->(). If it dies, it dies, and from the right place.

Notice your version will change the lines the errors are reported to be
emitted from. Eg, $SIG{__DIE__} will get called twice, once inside the
eval, and once when you throw the die. The visible error will be shown as
emitting from the line your die was called not the line where say, the
evalordie() would be called (presumably an XS version would not have this
problem). But if we split up the eval behavior into "compile" and "try"
behavior, then we dont have any of these issues.

So renaming the utility subs:

my $code= builtin::compile("10 add 22");
builtin::try($code,\&log_error); #renaming "builtin::execute" from above
example.

or with no compilation:

builtin::try(sub { call_thing($whatever) }, \&log_error);

cheers,
Yves
Re: New function suggestion: eval-or-die [ In reply to ]
On Tue, Sep 14, 2021 at 10:52:59AM -0400, Dan Book wrote:
> On Tue, Sep 14, 2021 at 6:37 AM David Cantrell <david@cantrell.org.uk>
> wrote:
> > The obvious problem is that your new syntax might legitimately evaluate
> > to C<undef> in a perl that supports it.
> This is allowed and part of the point. The pseudocode returns 1 from the
> evals to distinguish it from the error case, and a builtin would similarly
> not be result-dependent.

Ah yes, my mistake, I didn't read carefully enoguh :-)

--
David Cantrell | Official London Perl Mongers Bad Influence

Seven o'clock in the morning is something that
happens to those less fortunate than me
Re: New function suggestion: eval-or-die [ In reply to ]
wouldn't it be better just to throw proper exception ?
Re: New function suggestion: eval-or-die [ In reply to ]
On Wed, 15 Sept 2021 at 19:54, Branislav ZahradnĂ­k <happy.barney@gmail.com>
wrote:

>
> wouldn't it be better just to throw proper exception ?
>
>
Generally we have to constrain ourselves to solutions that dont render all
of the existing perl codebase broken.

Paul is proposing something that is IMO reasonable, even if I think it
could be achieved differently than he proposes.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"
Re: New function suggestion: eval-or-die [ In reply to ]
On Thu, 16 Sept 2021 at 11:11, demerphq <demerphq@gmail.com> wrote:

> On Wed, 15 Sept 2021 at 19:54, Branislav ZahradnĂ­k <happy.barney@gmail.com>
> wrote:
>
>>
>> wouldn't it be better just to throw proper exception ?
>>
>>
> Generally we have to constrain ourselves to solutions that dont render all
> of the existing perl codebase broken.
>
> Paul is proposing something that is IMO reasonable, even if I think it
> could be achieved differently than he proposes.
>
> Yves
>
>
a) introduce state "ref has attached package but is not blessed" (I started
experimenting with this, but on hold as everything)
b) introduced new variable, eg ${^Error} - will behave as $@ with
difference that every internal exception will be blessed



> --
> perl -Mre=debug -e "/just|another|perl|hacker/"
>
Re: New function suggestion: eval-or-die [ In reply to ]
On Thu, Sep 16, 2021 at 11:22:36AM +0200, Branislav Zahradn?k wrote:

> On Thu, 16 Sept 2021 at 11:11, demerphq <demerphq@gmail.com> wrote:
>
> > On Wed, 15 Sept 2021 at 19:54, Branislav Zahradn?k <happy.barney@gmail.com>
> > wrote:
> >
> >>
> >> wouldn't it be better just to throw proper exception ?
> >>
> >>
> > Generally we have to constrain ourselves to solutions that dont render all
> > of the existing perl codebase broken.
> >
> > Paul is proposing something that is IMO reasonable, even if I think it
> > could be achieved differently than he proposes.
> >
> > Yves
> >
> >
> a) introduce state "ref has attached package but is not blessed" (I started
> experimenting with this, but on hold as everything)

It's still unclear to me why this is necessary - ie why

"a reference to an object with overloaded stringification"

isn't sufficient to introduce "proper exceptions" without breaking existing
code which expects exceptions to behave as plain strings.

Nicholas Clark
Re: New function suggestion: eval-or-die [ In reply to ]
> >
> > >
> > a) introduce state "ref has attached package but is not blessed" (I
> started
> > experimenting with this, but on hold as everything)
>
> It's still unclear to me why this is necessary - ie why
>
> "a reference to an object with overloaded stringification"
>
> isn't sufficient to introduce "proper exceptions" without breaking existing
> code which expects exceptions to behave as plain strings.
>
>
reason: you can currently have something like:

eval ...;
if (blessed $@) { this is app exception }
if ($@) { this is non-app exception }

object with string overload will break it.



> Nicholas Clark
>
Re: New function suggestion: eval-or-die [ In reply to ]
On Mon, 13 Sep 2021 10:03:02 +0100
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> I feel it would be nice to provide a function of this behaviour in the
> new "builtins" space at some point. Needs a better name though -
> suggestions welcome.

Latest thoughts from PSC chats are that this probably wants to be
called `compile`, and should act similarish to

my $subref = compile $source;

my $subref = eval "sub { $source }" // die $@;

Though for now we'll park the idea while we actually get some progress
on the builtins namespace. Perhaps someone will come back to this after
that.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: New function suggestion: eval-or-die [ In reply to ]
On Fri, Nov 19, 2021, 07:42 Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> On Mon, 13 Sep 2021 10:03:02 +0100
>
> Latest thoughts from PSC chats are that this probably wants to be
> called `compile`, and should act similarish to
>
> my $subref = compile $source;
>
> my $subref = eval "sub { $source }" // die $@;
>
> Though for now we'll park the idea while we actually get some progress
> on the builtins namespace. Perhaps someone will come back to this after
> that.
>

Aside from prefixing $source with whatever it takes to change __FILE__ and
__LINE__ to make more sense, it looks like Acme::compile is ready to
publish.