Catching exceptions in expressions

--000000000000e3bddb05728c1b73
Content-Type: text/plain; charset="UTF-8"

I posted about this subject on Stack Overflow yesterday[1], but I chose a
poor example of something that raises an exception (dividing by zero, which
apparently doesn't necessarily do so) on which the answers have mostly
focused.

I was looking for a way to evaluate an expression, and if the expression
threw an exception, for a default value to be provided instead.  For
example, in Ruby:

    quotient = begin; a / b; rescue; -1; end

Or in Lisp:

    (setq quotient (condition-case nil (/ a b) (error -1)))

Not having written much exception-related code in Perl 6, I hoped that this
might work:

    sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }
    my $quotient = do { divide($a, $b); CATCH { default { -1 } } };

It doesn't, though.  As far as I can tell, the value to which a CATCH block
evaluates is ignored; the only useful things one can do in such a block are
things with side effects.  Long story short, I eventually came up with this:

    my $quotient = do { my $q; { $q = divide($a, $b); CATCH { default { $q
= -1 } } }; $q };

That's far more verbose than I've come to expect from Perl 6.  Is there
some more concise way of expressing this logic?

The doc page on exceptions mentions try, eg:

    my $quotient = try { divide($a, $b) } // -1;

That works in this specific case, but it seems insufficient in general.
The function might validly return an undefined value, and this construction
can't distinguish between that and an exception.  Also, it wouldn't let me
distinguish among various exception cases.  I'd have to do something like:

    class EA is Exception { }
    class EB is Exception { }
    sub divide($a, $b) { (EA, EB).pick.new.throw if $b == 0; $a / $b }

    my $quotient = do { my $q; { $q = divide($a, $b); CATCH { when EA { $q
= -1 }; when EB { $q = -2 } } }; $q };


[1]
https://stackoverflow.com/questions/51644197/returning-values-from-exception-handlers-in-perl-6/51670573

--000000000000e3bddb05728c1b73
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><div><div><div><div><div><div><div><div><div><div><di=
v><div><div><div><div>I posted about this subject on Stack Overflow yesterd=
ay[1], but I chose a poor example of something that raises an exception (di=
viding by zero, which apparently doesn&#39;t necessarily do so) on which th=
e answers have mostly focused.<br><br></div>I was looking for a way to eval=
uate an expression, and if the expression threw an exception, for a default=
 value to be provided instead.=C2=A0 For example, in Ruby:<br><br></div>=C2=
=A0=C2=A0=C2=A0 quotient =3D begin; a / b; rescue; -1; end<br><br></div>Or =
in Lisp:<br><br></div>=C2=A0=C2=A0=C2=A0 (setq quotient (condition-case nil=
 (/ a b) (error -1)))<br><br></div>Not having written much exception-relate=
d code in Perl 6, I hoped that this might work:<br><br></div><div>=C2=A0=C2=
=A0=C2=A0 sub divide($a, $b) { die &quot;Zero denominator&quot; if $b =3D=
=3D 0; $a / $b }<br></div>=C2=A0=C2=A0=C2=A0 my $quotient =3D do { divide($=
a, $b); CATCH { default { -1 } } };<br><br></div>It doesn&#39;t, though.=C2=
=A0 As far as I can tell, the value to which a CATCH block evaluates is ign=
ored; the only useful things one can do in such a block are things with sid=
e effects.=C2=A0 Long story short, I eventually came up with this:<br><br><=
/div>=C2=A0=C2=A0=C2=A0 my $quotient =3D do { my $q; { $q =3D divide($a, $b=
); CATCH { default { $q =3D -1 } } }; $q };<br><br></div>That&#39;s far mor=
e verbose than I&#39;ve come to expect from Perl 6.=C2=A0 Is there some mor=
e concise way of expressing this logic?<br><br></div>The doc page on except=
ions mentions try, eg:<br><br></div>=C2=A0=C2=A0=C2=A0 my $quotient =3D try=
 { divide($a, $b) } // -1;<br><br></div>That works in this specific case, b=
ut it seems insufficient in general.=C2=A0 The function might validly retur=
n an undefined value, and this construction can&#39;t distinguish between t=
hat and an exception.=C2=A0 Also, it wouldn&#39;t let me distinguish among =
various exception cases.=C2=A0 I&#39;d have to do something like:<br><br></=
div>=C2=A0=C2=A0=C2=A0 class EA is Exception { }<br></div>=C2=A0=C2=A0=C2=
=A0 class EB is Exception { }<br></div>=C2=A0=C2=A0=C2=A0 sub divide($a, $b=
) { (EA, EB).pick.new.throw if $b =3D=3D 0; $a / $b }<br></div><br>=C2=A0=
=C2=A0=C2=A0 my $quotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { =
when EA { $q =3D -1 }; when EB { $q =3D -2 } } }; $q };<br><br><br>[1] <a h=
ref=3D"https://stackoverflow.com/questions/51644197/returning-values-from-e=
xception-handlers-in-perl-6/51670573">https://stackoverflow.com/questions/5=
1644197/returning-values-from-exception-handlers-in-perl-6/51670573</a><br>=
</div>

--000000000000e3bddb05728c1b73--
0
eefacm
8/3/2018 6:29:31 PM
perl.perl6.users 1089 articles. 0 followers. Follow

4 Replies
34 Views

Similar Articles

[PageSpeed] 0

--000000000000aab57a05728d052b
Content-Type: text/plain; charset="UTF-8"

Hi Sean. I hope my second answer in stackoverflow gets closer to what you
want.

I am still trying to think of a more idiomatic way of handling to situation.



On Fri, 3 Aug 2018, 19:29 Sean McAfee, <eefacm@gmail.com> wrote:

> I posted about this subject on Stack Overflow yesterday[1], but I chose a
> poor example of something that raises an exception (dividing by zero, which
> apparently doesn't necessarily do so) on which the answers have mostly
> focused.
>
> I was looking for a way to evaluate an expression, and if the expression
> threw an exception, for a default value to be provided instead.  For
> example, in Ruby:
>
>     quotient = begin; a / b; rescue; -1; end
>
> Or in Lisp:
>
>     (setq quotient (condition-case nil (/ a b) (error -1)))
>
> Not having written much exception-related code in Perl 6, I hoped that
> this might work:
>
>     sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }
>     my $quotient = do { divide($a, $b); CATCH { default { -1 } } };
>
> It doesn't, though.  As far as I can tell, the value to which a CATCH
> block evaluates is ignored; the only useful things one can do in such a
> block are things with side effects.  Long story short, I eventually came up
> with this:
>
>     my $quotient = do { my $q; { $q = divide($a, $b); CATCH { default { $q
> = -1 } } }; $q };
>
> That's far more verbose than I've come to expect from Perl 6.  Is there
> some more concise way of expressing this logic?
>
> The doc page on exceptions mentions try, eg:
>
>     my $quotient = try { divide($a, $b) } // -1;
>
> That works in this specific case, but it seems insufficient in general.
> The function might validly return an undefined value, and this construction
> can't distinguish between that and an exception.  Also, it wouldn't let me
> distinguish among various exception cases.  I'd have to do something like:
>
>     class EA is Exception { }
>     class EB is Exception { }
>     sub divide($a, $b) { (EA, EB).pick.new.throw if $b == 0; $a / $b }
>
>     my $quotient = do { my $q; { $q = divide($a, $b); CATCH { when EA { $q
> = -1 }; when EB { $q = -2 } } }; $q };
>
>
> [1]
> https://stackoverflow.com/questions/51644197/returning-values-from-exception-handlers-in-perl-6/51670573
>
-- 
Simon Proctor
Cognoscite aliquid novum cotidie

--000000000000aab57a05728d052b
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi Sean. I hope my second answer in stackoverflow gets closer to what you w=
ant.=C2=A0<div><br></div><div>I am still trying to think of a more idiomati=
c way of handling to situation.</div><div><br></div><div><br></div><div><br=
><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, 3 Aug 2018, 19:29 Sean=
 McAfee, &lt;<a href=3D"mailto:eefacm@gmail.com">eefacm@gmail.com</a>&gt; w=
rote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div><d=
iv><div><div><div><div><div><div><div><div><div><div><div><div><div>I poste=
d about this subject on Stack Overflow yesterday[1], but I chose a poor exa=
mple of something that raises an exception (dividing by zero, which apparen=
tly doesn&#39;t necessarily do so) on which the answers have mostly focused=
..<br><br></div>I was looking for a way to evaluate an expression, and if th=
e expression threw an exception, for a default value to be provided instead=
..=C2=A0 For example, in Ruby:<br><br></div>=C2=A0=C2=A0=C2=A0 quotient =3D =
begin; a / b; rescue; -1; end<br><br></div>Or in Lisp:<br><br></div>=C2=A0=
=C2=A0=C2=A0 (setq quotient (condition-case nil (/ a b) (error -1)))<br><br=
></div>Not having written much exception-related code in Perl 6, I hoped th=
at this might work:<br><br></div><div>=C2=A0=C2=A0=C2=A0 sub divide($a, $b)=
 { die &quot;Zero denominator&quot; if $b =3D=3D 0; $a / $b }<br></div>=C2=
=A0=C2=A0=C2=A0 my $quotient =3D do { divide($a, $b); CATCH { default { -1 =
} } };<br><br></div>It doesn&#39;t, though.=C2=A0 As far as I can tell, the=
 value to which a CATCH block evaluates is ignored; the only useful things =
one can do in such a block are things with side effects.=C2=A0 Long story s=
hort, I eventually came up with this:<br><br></div>=C2=A0=C2=A0=C2=A0 my $q=
uotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { default { $q =3D -=
1 } } }; $q };<br><br></div>That&#39;s far more verbose than I&#39;ve come =
to expect from Perl 6.=C2=A0 Is there some more concise way of expressing t=
his logic?<br><br></div>The doc page on exceptions mentions try, eg:<br><br=
></div>=C2=A0=C2=A0=C2=A0 my $quotient =3D try { divide($a, $b) } // -1;<br=
><br></div>That works in this specific case, but it seems insufficient in g=
eneral.=C2=A0 The function might validly return an undefined value, and thi=
s construction can&#39;t distinguish between that and an exception.=C2=A0 A=
lso, it wouldn&#39;t let me distinguish among various exception cases.=C2=
=A0 I&#39;d have to do something like:<br><br></div>=C2=A0=C2=A0=C2=A0 clas=
s EA is Exception { }<br></div>=C2=A0=C2=A0=C2=A0 class EB is Exception { }=
<br></div>=C2=A0=C2=A0=C2=A0 sub divide($a, $b) { (EA, EB).pick.new.throw i=
f $b =3D=3D 0; $a / $b }<br></div><br>=C2=A0=C2=A0=C2=A0 my $quotient =3D d=
o { my $q; { $q =3D divide($a, $b); CATCH { when EA { $q =3D -1 }; when EB =
{ $q =3D -2 } } }; $q };<br><br><br>[1] <a href=3D"https://stackoverflow.co=
m/questions/51644197/returning-values-from-exception-handlers-in-perl-6/516=
70573" target=3D"_blank">https://stackoverflow.com/questions/51644197/retur=
ning-values-from-exception-handlers-in-perl-6/51670573</a><br></div>
</blockquote></div></div>-- <br><div dir=3D"ltr" class=3D"gmail_signature" =
data-smartmail=3D"gmail_signature"><div dir=3D"ltr"><font size=3D"-1"><font=
 color=3D"#888888">Simon Proctor<br>
Cognoscite aliquid novum cotidie</font></font></div></div>

--000000000000aab57a05728d052b--
0
simon
8/3/2018 7:34:44 PM
Maybe something like...?

$ cat t.p6

sub infix:<rescue>(Callable $block, $otherwise) { 
   CATCH { return $otherwise; }
   $block();
}

sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }

my $sixdivzero = { divide(6,0) } rescue -1;
say "6/0 = ", $sixdivzero;

my $sixdivtwo = { divide(6,2) } rescue -1;
say "6/2 = ", $sixdivtwo;


$ perl6 t.p6
6/0 = -1
6/2 = 3


Or if you prefer a prefix form, just declare "rescue" as a normal sub and then do:

   rescue { divide(6,2) }, -1;

Pm

On Fri, Aug 03, 2018 at 08:34:44PM +0100, Simon Proctor wrote:
> Hi Sean. I hope my second answer in stackoverflow gets closer to what you
> want.
> 
> I am still trying to think of a more idiomatic way of handling to situation.
> 
> 
> 
> On Fri, 3 Aug 2018, 19:29 Sean McAfee, <eefacm@gmail.com> wrote:
> 
> > I posted about this subject on Stack Overflow yesterday[1], but I chose a
> > poor example of something that raises an exception (dividing by zero, which
> > apparently doesn't necessarily do so) on which the answers have mostly
> > focused.
> >
> > I was looking for a way to evaluate an expression, and if the expression
> > threw an exception, for a default value to be provided instead.  For
> > example, in Ruby:
> >
> >     quotient = begin; a / b; rescue; -1; end
> >
> > Or in Lisp:
> >
> >     (setq quotient (condition-case nil (/ a b) (error -1)))
> >
> > Not having written much exception-related code in Perl 6, I hoped that
> > this might work:
> >
> >     sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }
> >     my $quotient = do { divide($a, $b); CATCH { default { -1 } } };
> >
> > It doesn't, though.  As far as I can tell, the value to which a CATCH
> > block evaluates is ignored; the only useful things one can do in such a
> > block are things with side effects.  Long story short, I eventually came up
> > with this:
> >
> >     my $quotient = do { my $q; { $q = divide($a, $b); CATCH { default { $q
> > = -1 } } }; $q };
> >
> > That's far more verbose than I've come to expect from Perl 6.  Is there
> > some more concise way of expressing this logic?
> >
> > The doc page on exceptions mentions try, eg:
> >
> >     my $quotient = try { divide($a, $b) } // -1;
> >
> > That works in this specific case, but it seems insufficient in general.
> > The function might validly return an undefined value, and this construction
> > can't distinguish between that and an exception.  Also, it wouldn't let me
> > distinguish among various exception cases.  I'd have to do something like:
> >
> >     class EA is Exception { }
> >     class EB is Exception { }
> >     sub divide($a, $b) { (EA, EB).pick.new.throw if $b == 0; $a / $b }
> >
> >     my $quotient = do { my $q; { $q = divide($a, $b); CATCH { when EA { $q
> > = -1 }; when EB { $q = -2 } } }; $q };
> >
> >
> > [1]
> > https://stackoverflow.com/questions/51644197/returning-values-from-exception-handlers-in-perl-6/51670573
> >
> -- 
> Simon Proctor
> Cognoscite aliquid novum cotidie
0
pmichaud
8/3/2018 8:18:53 PM
Sometimes I wish we could use Thunk as a type:

sub infix:<rescue>(Thunk:D $block, $otherwise) { }

which would then allow you to do:

my $sixdivzero =3D divide(6,0) rescue -1;  # note absence of curlies



One can wish, can=E2=80=99t one?


Liz

> On 3 Aug 2018, at 22:18, Patrick R. Michaud <pmichaud@pobox.com> =
wrote:
>=20
> Maybe something like...?
>=20
> $ cat t.p6
>=20
> sub infix:<rescue>(Callable $block, $otherwise) {=20
>   CATCH { return $otherwise; }
>   $block();
> }
>=20
> sub divide($a, $b) { die "Zero denominator" if $b =3D=3D 0; $a / $b }
>=20
> my $sixdivzero =3D { divide(6,0) } rescue -1;
> say "6/0 =3D ", $sixdivzero;
>=20
> my $sixdivtwo =3D { divide(6,2) } rescue -1;
> say "6/2 =3D ", $sixdivtwo;
>=20
>=20
> $ perl6 t.p6
> 6/0 =3D -1
> 6/2 =3D 3
>=20
>=20
> Or if you prefer a prefix form, just declare "rescue" as a normal sub =
and then do:
>=20
>   rescue { divide(6,2) }, -1;
>=20
> Pm
>=20
> On Fri, Aug 03, 2018 at 08:34:44PM +0100, Simon Proctor wrote:
>> Hi Sean. I hope my second answer in stackoverflow gets closer to what =
you
>> want.
>>=20
>> I am still trying to think of a more idiomatic way of handling to =
situation.
>>=20
>>=20
>>=20
>> On Fri, 3 Aug 2018, 19:29 Sean McAfee, <eefacm@gmail.com> wrote:
>>=20
>>> I posted about this subject on Stack Overflow yesterday[1], but I =
chose a
>>> poor example of something that raises an exception (dividing by =
zero, which
>>> apparently doesn't necessarily do so) on which the answers have =
mostly
>>> focused.
>>>=20
>>> I was looking for a way to evaluate an expression, and if the =
expression
>>> threw an exception, for a default value to be provided instead.  For
>>> example, in Ruby:
>>>=20
>>>    quotient =3D begin; a / b; rescue; -1; end
>>>=20
>>> Or in Lisp:
>>>=20
>>>    (setq quotient (condition-case nil (/ a b) (error -1)))
>>>=20
>>> Not having written much exception-related code in Perl 6, I hoped =
that
>>> this might work:
>>>=20
>>>    sub divide($a, $b) { die "Zero denominator" if $b =3D=3D 0; $a / =
$b }
>>>    my $quotient =3D do { divide($a, $b); CATCH { default { -1 } } };
>>>=20
>>> It doesn't, though.  As far as I can tell, the value to which a =
CATCH
>>> block evaluates is ignored; the only useful things one can do in =
such a
>>> block are things with side effects.  Long story short, I eventually =
came up
>>> with this:
>>>=20
>>>    my $quotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { =
default { $q
>>> =3D -1 } } }; $q };
>>>=20
>>> That's far more verbose than I've come to expect from Perl 6.  Is =
there
>>> some more concise way of expressing this logic?
>>>=20
>>> The doc page on exceptions mentions try, eg:
>>>=20
>>>    my $quotient =3D try { divide($a, $b) } // -1;
>>>=20
>>> That works in this specific case, but it seems insufficient in =
general.
>>> The function might validly return an undefined value, and this =
construction
>>> can't distinguish between that and an exception.  Also, it wouldn't =
let me
>>> distinguish among various exception cases.  I'd have to do something =
like:
>>>=20
>>>    class EA is Exception { }
>>>    class EB is Exception { }
>>>    sub divide($a, $b) { (EA, EB).pick.new.throw if $b =3D=3D 0; $a / =
$b }
>>>=20
>>>    my $quotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { =
when EA { $q
>>> =3D -1 }; when EB { $q =3D -2 } } }; $q };
>>>=20
>>>=20
>>> [1]
>>> =
https://stackoverflow.com/questions/51644197/returning-values-from-excepti=
on-handlers-in-perl-6/51670573
>>>=20
>> --=20
>> Simon Proctor
>> Cognoscite aliquid novum cotidie
0
liz
8/3/2018 8:32:41 PM
Yes; but then I think that something like infix:<rescue> probably just en=
ds up as a macro somehow.  I just didn't know the state of macros in Perl=
 6 well enough to be able to head down that route.  :)

Pm

On Fri, Aug 03, 2018 at 10:32:41PM +0200, Elizabeth Mattijsen wrote:
> Sometimes I wish we could use Thunk as a type:
>=20
> sub infix:<rescue>(Thunk:D $block, $otherwise) { }
>=20
> which would then allow you to do:
>=20
> my $sixdivzero =3D divide(6,0) rescue -1;  # note absence of curlies
>=20
>=20
>=20
> One can wish, can=E2=80=99t one?
>=20
>=20
> Liz
>=20
> > On 3 Aug 2018, at 22:18, Patrick R. Michaud <pmichaud@pobox.com> wrot=
e:
> >=20
> > Maybe something like...?
> >=20
> > $ cat t.p6
> >=20
> > sub infix:<rescue>(Callable $block, $otherwise) {=20
> >   CATCH { return $otherwise; }
> >   $block();
> > }
> >=20
> > sub divide($a, $b) { die "Zero denominator" if $b =3D=3D 0; $a / $b }
> >=20
> > my $sixdivzero =3D { divide(6,0) } rescue -1;
> > say "6/0 =3D ", $sixdivzero;
> >=20
> > my $sixdivtwo =3D { divide(6,2) } rescue -1;
> > say "6/2 =3D ", $sixdivtwo;
> >=20
> >=20
> > $ perl6 t.p6
> > 6/0 =3D -1
> > 6/2 =3D 3
> >=20
> >=20
> > Or if you prefer a prefix form, just declare "rescue" as a normal sub=
 and then do:
> >=20
> >   rescue { divide(6,2) }, -1;
> >=20
> > Pm
> >=20
> > On Fri, Aug 03, 2018 at 08:34:44PM +0100, Simon Proctor wrote:
> >> Hi Sean. I hope my second answer in stackoverflow gets closer to wha=
t you
> >> want.
> >>=20
> >> I am still trying to think of a more idiomatic way of handling to si=
tuation.
> >>=20
> >>=20
> >>=20
> >> On Fri, 3 Aug 2018, 19:29 Sean McAfee, <eefacm@gmail.com> wrote:
> >>=20
> >>> I posted about this subject on Stack Overflow yesterday[1], but I c=
hose a
> >>> poor example of something that raises an exception (dividing by zer=
o, which
> >>> apparently doesn't necessarily do so) on which the answers have mos=
tly
> >>> focused.
> >>>=20
> >>> I was looking for a way to evaluate an expression, and if the expre=
ssion
> >>> threw an exception, for a default value to be provided instead.  Fo=
r
> >>> example, in Ruby:
> >>>=20
> >>>    quotient =3D begin; a / b; rescue; -1; end
> >>>=20
> >>> Or in Lisp:
> >>>=20
> >>>    (setq quotient (condition-case nil (/ a b) (error -1)))
> >>>=20
> >>> Not having written much exception-related code in Perl 6, I hoped t=
hat
> >>> this might work:
> >>>=20
> >>>    sub divide($a, $b) { die "Zero denominator" if $b =3D=3D 0; $a /=
 $b }
> >>>    my $quotient =3D do { divide($a, $b); CATCH { default { -1 } } }=
;
> >>>=20
> >>> It doesn't, though.  As far as I can tell, the value to which a CAT=
CH
> >>> block evaluates is ignored; the only useful things one can do in su=
ch a
> >>> block are things with side effects.  Long story short, I eventually=
 came up
> >>> with this:
> >>>=20
> >>>    my $quotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { de=
fault { $q
> >>> =3D -1 } } }; $q };
> >>>=20
> >>> That's far more verbose than I've come to expect from Perl 6.  Is t=
here
> >>> some more concise way of expressing this logic?
> >>>=20
> >>> The doc page on exceptions mentions try, eg:
> >>>=20
> >>>    my $quotient =3D try { divide($a, $b) } // -1;
> >>>=20
> >>> That works in this specific case, but it seems insufficient in gene=
ral.
> >>> The function might validly return an undefined value, and this cons=
truction
> >>> can't distinguish between that and an exception.  Also, it wouldn't=
 let me
> >>> distinguish among various exception cases.  I'd have to do somethin=
g like:
> >>>=20
> >>>    class EA is Exception { }
> >>>    class EB is Exception { }
> >>>    sub divide($a, $b) { (EA, EB).pick.new.throw if $b =3D=3D 0; $a =
/ $b }
> >>>=20
> >>>    my $quotient =3D do { my $q; { $q =3D divide($a, $b); CATCH { wh=
en EA { $q
> >>> =3D -1 }; when EB { $q =3D -2 } } }; $q };
> >>>=20
> >>>=20
> >>> [1]
> >>> https://stackoverflow.com/questions/51644197/returning-values-from-=
exception-handlers-in-perl-6/51670573
> >>>=20
> >> --=20
> >> Simon Proctor
> >> Cognoscite aliquid novum cotidie
0
pmichaud
8/4/2018 12:47:16 AM
Reply: