Mailing List Archive

try catch except python
Here is the Python equivalent of try/catch:

try:
x = 1/0except:
print('Something went wrong.')


Please note that *except* does not require a parenthesised parameter list.
And if they had used *fail *instead of *except* it would have not only made
sense, but it would have been shorter and easier to spell as well.

Are we so determined to look like Java, to the very last parenthesis, that
we are willing to abandon the important Perl traditions of using short
words, making parentheses optional and leading the way rather than being
mere followers? As Enzo Ferrari might have said to Lee Iacocca: "Torna
alla sua grande, brutta fabbrica, a fare le sue brutte macchinine".

--
Thanks,

Phil <https://metacpan.org/author/PRBRENAN>

Philip R Brenan <https://metacpan.org/author/PRBRENAN>
Re: try catch except python [ In reply to ]
On Mon, 25 Jan 2021 14:09:42 +0000
Philip R Brenan <philiprbrenan@gmail.com> wrote:

> Are we so determined to look like Java, to the very last parenthesis,
> that we are willing to abandon the important Perl traditions of
> using short words, making parentheses optional and leading the way
> rather than being mere followers? As Enzo Ferrari might have said to
> Lee Iacocca: "Torna alla sua grande, brutta fabbrica, a fare le sue
> brutte macchinine".

The parens are there to support typed dispatch; see
Syntax::Keyword::Try:

https://metacpan.org/pod/Syntax::Keyword::Try#catch-(Typed)

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: try catch except python [ In reply to ]
> On Jan 25, 2021, at 10:01 AM, Paul LeoNerd Evans <leonerd@leonerd.org.uk> wrote:
>
> On Mon, 25 Jan 2021 14:09:42 +0000
> Philip R Brenan <philiprbrenan@gmail.com> wrote:
>
>> Are we so determined to look like Java, to the very last parenthesis,
>> that we are willing to abandon the important Perl traditions of
>> using short words, making parentheses optional and leading the way
>> rather than being mere followers? As Enzo Ferrari might have said to
>> Lee Iacocca: "Torna alla sua grande, brutta fabbrica, a fare le sue
>> brutte macchinine".
>
> The parens are there to support typed dispatch; see
> Syntax::Keyword::Try:
>
> https://metacpan.org/pod/Syntax::Keyword::Try#catch-(Typed)

To play a bit of devil’s advocate: one nicety of S::K::T’s current interface is that PROPAGATE() behaviour happens “naturally”, e.g.:

-----
> perl -MSyntax::Keyword::Try -e'try { die "haha" } catch { die }'
haha at -e line 1.
...propagated at -e line 1.
-----

PROPAGATE() only happens when you die() (or warn()) with no arguments. Making that happen with the parens requires a bit more work:

> perl -MSyntax::Keyword::Try -e'try { die "haha" } catch ($e) { $@ = $e; die }'

Would there be benefit in allowing an unadorned `catch {..}` as an alternative to the parenthesized one?

And will $@ continue to be set within the catch block even if $e also contains that value (as S::K::T currently does)?

-F
Re: try catch except python [ In reply to ]
On Mon, Jan 25, 2021, at 10:12 AM, Felipe Gasper wrote:
> Would there be benefit in allowing an unadorned `catch {..}` as an alternative to the parenthesized one?
>
> And will $@ continue to be set within the catch block even if $e also contains that value (as S::K::T currently does)?

I'm trying to decide whether this seems really compelling or only superficially compelling. So far, I'm not sure.

Another form of this question is: is catch more like a subroutine or more like a for loop? :-)

Consider:
for my $x (@list) { ... }
for $x (@list) { ... }
for (@list) { ... }

The default is "we have a built in variable for this" — $_ for for loops, $@ for catch — and you can replace it if you want. It is strictly singular, so you can provide the name of an existing variable, or even declare one lexically scoped to this block. You have to say "my" because an existing variable is permitted.

Meanwhile:
sub declaim ($message) { ... }

There is no default target for parameter copying. (@_ is doing a distinct job.) Since the variable must be declared anew, and must be lexical, there's no need to say "my". We have it in our heads, sometimes, that the inside of the parentheses on a subroutine signature is a nascent grammar of its own, waiting for many new purposes, like parametric type constraints.

Do we want to allow catch ($x){} to use an existing $x, meaning we need a "my" on every other use? This seems excessively niche and likely to lead to confusion. Using a my-less one-part for variable can be neat, but mostly I think it's dead weight. Also, requiring "my" for the common case is a drag.

If the parametric syntax for subroutines and catch can be unified, that seems like a real win. It could become a pattern to be used in a number of places. (A new for-ish loop with a parameter list in place of a single bind value? I'd use it.) So, that implies "catch ($e) { ... }" but the remaining question is: do you need that parameter list?

Well, the behavior of subroutines without a signature is "you look at @_, which is different than the ($x, $y) you would've gotten from a signature." You get aliases instead of copies, there's no arity, and other minor perils apply. Is it reasonable to say "if you have no parameter list for catch, you just look at $@, which has some peril"?

I think it is, if and only if that peril is sufficiently clear. Back in the bad old days before 5.14, we used to worry that $@ might vanish before the statement after eval. That is:
1: eval {
2: my $magic = Magic->new;
3:
4: if ($doomed) { die "Oh no!" };
5: };
6:
7: if ($@) {
8: print "Died: $@";
9: }

This code was a smell, because Magic might provide a DESTROY. Line 4 would set $@, and during the cleanup executed when the eval block's scope was torn down at line 5, the Magic DESTROY would run its own eval, clearing $@. Then the code on line 8 never ran, because $@ was false. Wauugh. This led to all kinds of horrible gyrations, but I think they're now totally unneeded. $@ is reliable — or so close to it that I have not encountered this problem since 5.14.

One *still* wants to copy $@, because any subroutine inside the "if ($@)" might still clobber it. But if there are no subroutines, if the programmer really knows what they're doing, trusting $@ is not crazy. I think if we can say "when catch is entered, $@ has the same value that was thrown with die, with the same guarantees as at the end of an eval", then allowing a no-parameter catch block seems reasonable and in line with other parts of the language.

(For all this typing, this isn't a hill to die on. I just think it's worth looking at the ways in which this feature would or could echo the rest of the language.)

Paul, what do you think?

--
rjbs
Re: try catch except python [ In reply to ]
On Mon, Jan 25, 2021 at 10:52 PM Ricardo Signes <perl.p5p@rjbs.manxome.org>
wrote:

> Consider:
>
> for my $x (@list) { ... }
> for $x (@list) { ... }
> for (@list) { ... }
>
>
> The default is "we have a built in variable for this" — $_ for for loops,
> $@ for catch — and you can replace it if you want. It is strictly
> singular, so you can provide the name of an existing variable, or even
> declare one lexically scoped to this block. You have to say "my" because
> an existing variable is permitted.
>

Editor's note: this doesn't actually let you use an existing variable - it
shadows the variable in some weird way and we would be better off without
this feature.

-Dan
Re: try catch except python [ In reply to ]
On Mon, 25 Jan 2021 22:58:18 -0500
Dan Book <grinnz@gmail.com> wrote:

> On Mon, Jan 25, 2021 at 10:52 PM Ricardo Signes <perl.p5p@rjbs.manxome.org>
> wrote:
>
> > Consider:
> >
> > for my $x (@list) { ... }
> > for $x (@list) { ... }
> > for (@list) { ... }
> >
> >
> > The default is "we have a built in variable for this" ? $_ for for loops,
> > $@ for catch ? and you can replace it if you want. It is strictly
> > singular, so you can provide the name of an existing variable, or even
> > declare one lexically scoped to this block. You have to say "my" because
> > an existing variable is permitted.
> >
>
> Editor's note: this doesn't actually let you use an existing variable - it
> shadows the variable in some weird way and we would be better off without
> this feature.
>
> -Dan

Come to think of it, is there any reason why we shouldn't make "for $x"
do exactly the same thing as "for my $x"? Would that break anything?
Re: try catch except python [ In reply to ]
On Tue, Jan 26, 2021 at 12:46 AM Tomasz Konojacki <me@xenu.pl> wrote:

> On Mon, 25 Jan 2021 22:58:18 -0500
> Dan Book <grinnz@gmail.com> wrote:
>
> > On Mon, Jan 25, 2021 at 10:52 PM Ricardo Signes <
> perl.p5p@rjbs.manxome.org>
> > wrote:
> >
> > > Consider:
> > >
> > > for my $x (@list) { ... }
> > > for $x (@list) { ... }
> > > for (@list) { ... }
> > >
> > >
> > > The default is "we have a built in variable for this" $_ for for
> loops,
> > > $@ for catch and you can replace it if you want. It is strictly
> > > singular, so you can provide the name of an existing variable, or even
> > > declare one lexically scoped to this block. You have to say "my"
> because
> > > an existing variable is permitted.
> > >
> >
> > Editor's note: this doesn't actually let you use an existing variable -
> it
> > shadows the variable in some weird way and we would be better off without
> > this feature.
> >
> > -Dan
>
> Come to think of it, is there any reason why we shouldn't make "for $x"
> do exactly the same thing as "for my $x"? Would that break anything?
>
>
The one thing it would break is that if it's a package variable it's
shadowing, it's still global, much like the localized $_ so other code can
affect/be affected by it unlike a lexical.

-Dan
Re: try catch except python [ In reply to ]
Thanks rjbs for giving some thought; my replies below...


On Mon, 25 Jan 2021 22:51:23 -0500
"Ricardo Signes" <perl.p5p@rjbs.manxome.org> wrote:

> Another form of this question is: is catch more like a subroutine or
> more like a for loop? :-)
...
>
> Meanwhile:
> sub declaim ($message) { ... }
...
> If the parametric syntax for subroutines and catch can be unified,
> that seems like a real win. It could become a pattern to be used in
> a number of places. (A new for-ish loop with a parameter list in
> place of a single bind value? I'd use it.) So, that implies "catch
> ($e) { ... }" but the remaining question is: do you need that
> parameter list?

This was verymuch my unifying thought, yes. As laid out by

https://rt.cpan.org/Ticket/Display.html?id=123918#txn-1903905

(hoping that rt.cpan.org links survive into posterity)

Originally I considered it like a for loop, and it was even spelled
`catch my $VAR { ... }` looking very similar. But I found we couldn't
get the typed conditional dispatch in there in any sensible syntax. So
we looked at other things - ilmari suggested the overlap with
signatures.

The basic observation is that there's some syntax similarity along with
the similar behaviours of

catch ($e) { ... }

sub f ($x) { ... }

and I was planning to keep them similar while adding things like `isa`
or `is` type assertions. One can imagine

try { ... }
catch ($e isa SomeException) { ... }
catch ($e isa DifferentException) { ... }

somewhat similar to a sortof multiple dispatch on `multi sub`:

multi sub _catch($e isa SomeException) { ... }
multi sub _catch($e isa DifferentException) { ... }

The similar spelling of the items in parens here follows through to a
deeper similarity in the implicit creation of those lexical variables
and the type assertions for dispatching on them.

I also have a few other thoughts of a few additional language
constructions that again follow similar ideas of looking like
signatures/catch with typed assertions as some sort of conditional
dispatch. I'll be saying more on that subject in my FOSDEM talk - so
perhaps I'll come back to reply here again when that happens on
Feb 6th.

> Well, the behavior of subroutines without a signature is "you look at
> @_, which is different than the ($x, $y) you would've gotten from a
> signature." You get aliases instead of copies, there's no arity, and
> other minor perils apply. Is it reasonable to say "if you have no
> parameter list for catch, you just look at $@, which has some peril"?
...
> One *still* wants to copy $@, because any subroutine inside the "if
> ($@)" might still clobber it. But if there are no subroutines, if
> the programmer really knows what they're doing, trusting $@ is not
> crazy. I think if we can say "when catch is entered, $@ has the same
> value that was thrown with die, with the same guarantees as at the
> end of an eval", then allowing a no-parameter catch block seems
> reasonable and in line with other parts of the language.

I considered allowing that, but I didn't really feel there were any
strong reasons for doing so just yet. There's certainly no
backward-compatibility problem as it is a new syntax. We might as well
start with the most restrictive rules (catch must declare a var), and
if later on we find that keeps getting in the way because people
genuinely do want an unvariabled catch to assign into $@ with all the
volatility risks that involves, we can expand the grammar to allow it.
(Though at that point I'd wonder how you do a `isa` typed catch without
a var).

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: try catch except python [ In reply to ]
On Mon, Jan 25, 2021, at 10:58 PM, Dan Book wrote:
> On Mon, Jan 25, 2021 at 10:52 PM Ricardo Signes <perl.p5p@rjbs.manxome.org> wrote:
>> The default is "we have a built in variable for this" — $_ for for loops, $@ for catch — and you can replace it if you want. It is strictly singular, so you can provide the name of an existing variable, or even declare one lexically scoped to this block. You have to say "my" because an existing variable is permitted.
>
> Editor's note: this doesn't actually let you use an existing variable - it shadows the variable in some weird way and we would be better off without this feature.

This is not correct.

our $x = 100;

sub say_x { say "X is $x" }

say_x;

for $x (1..2) { say_x }

say_x;

The for loop is using the same $x. It is not shadowing it in "some weird way". It is localizing it in dynamic scope, just like the local keyword would.

I don't think it's right to get into "we would be better off without this feature" when you don't grasp what it does.

--
rjbs
Re: try catch except python [ In reply to ]
> On Jan 26, 2021, at 5:44 AM, Paul LeoNerd Evans <leonerd@leonerd.org.uk> wrote:
>
> On Mon, 25 Jan 2021 22:51:23 -0500
> "Ricardo Signes" <perl.p5p@rjbs.manxome.org> wrote:
>
>> One *still* wants to copy $@, because any subroutine inside the "if
>> ($@)" might still clobber it. But if there are no subroutines, if
>> the programmer really knows what they're doing, trusting $@ is not
>> crazy. I think if we can say "when catch is entered, $@ has the same
>> value that was thrown with die, with the same guarantees as at the
>> end of an eval", then allowing a no-parameter catch block seems
>> reasonable and in line with other parts of the language.
>
> I considered allowing that, but I didn't really feel there were any
> strong reasons for doing so just yet. There's certainly no
> backward-compatibility problem as it is a new syntax. We might as well
> start with the most restrictive rules (catch must declare a var), and
> if later on we find that keeps getting in the way because people
> genuinely do want an unvariabled catch to assign into $@ with all the
> volatility risks that involves, we can expand the grammar to allow it.
> (Though at that point I'd wonder how you do a `isa` typed catch without
> a var).

Maybe:

try { .. }
catch ($@ isa 'X::Foo') { .. }
catch ($@ isa 'X::Bar') { .. }
catch { .. }

-F
Re: try catch except python [ In reply to ]
On Tue, Jan 26, 2021, at 8:30 AM, Ricardo Signes wrote:
> On Mon, Jan 25, 2021, at 10:58 PM, Dan Book wrote:
>> Editor's note: this doesn't actually let you use an existing variable - it shadows the variable in some weird way and we would be better off without this feature.
>
> This is not correct.
> [… stuff about localizing package variables …]
> I don't think it's right to get into "we would be better off without this feature" when you don't grasp what it does.

So, in a later post you allude to this, so I guess you meant only the shadowing of existing *lexical* variables. I apologize for disambiguating toward the worse, rather than better, read. I'm so weary of the low-grade litany of "this feature is not something I use or understand, and so perl could benefit from its removal." It's so often ill-informed that I have become sensitized to it.

I hesitate to say much about the utility of the use of preexisting lexicals as the binding target of a for loop. I've never done it on purpose…

--
rjbs
Re: try catch except python [ In reply to ]
On Mon, Jan 25, 2021 at 10:51:23PM -0500, Ricardo Signes wrote:

> Another form of this question is: is catch more like a subroutine or more like a for loop? :-)
>
> Consider:
> for my $x (@list) { ... }
> for $x (@list) { ... }
> for (@list) { ... }
>
> The default is "we have a built in variable for this" ??? $_ for for loops, $@ for catch ??? and you can replace it if you want. It is strictly singular, so you can provide the name of an existing variable, or even declare one lexically scoped to this block. You have to say "my" because an existing variable is permitted.
>
> Meanwhile:
> sub declaim ($message) { ... }
>
> There is no default target for parameter copying. (@_ is doing a distinct job.) Since the variable must be declared anew, and must be lexical, there's no need to say "my". We have it in our heads, sometimes, that the inside of the parentheses on a subroutine signature is a nascent grammar of its own, waiting for many new purposes, like parametric type constraints.
>
> Do we want to allow catch ($x){} to use an existing $x, meaning we need a "my" on every other use?

Does it make sense to talk about `catch ($x) {}` using an existing $x? I
don't think so. The parameter passed in will surely always be the
exception caught in the immediately preceding `try {}`. If the
programmer wants to refer to a pre-existing `$x` inside the catch block
in addition to referring to the exception then he can write
`catch($some_other_variable_name) {}`. But he will *never* want to pass
some pre-existing `$x` into the catch block *instead of* passing in the
exception. If he wants to ignore what the exception was altogether and
just get called if there was one, then paren-less `catch {}` would seem
appropriate.

--
David Cantrell

Your call is important to me. To see if it's important to
you I'm going to make you wait on hold for five minutes.
All calls are recorded for blackmail and amusement purposes.
Re: try catch except python [ In reply to ]
On Tue, Jan 26, 2021 at 9:00 AM Ricardo Signes <perl.p5p@rjbs.manxome.org>
wrote:

> On Tue, Jan 26, 2021, at 8:30 AM, Ricardo Signes wrote:
>
> On Mon, Jan 25, 2021, at 10:58 PM, Dan Book wrote:
>
> Editor's note: this doesn't actually let you use an existing variable - it
> shadows the variable in some weird way and we would be better off without
> this feature.
>
>
> This is not correct.
> [… stuff about localizing package variables …]
> I don't think it's right to get into "we would be better off without this
> feature" when you don't grasp what it does.
>
>
> So, in a later post you allude to this, so I guess you meant only the
> shadowing of existing *lexical* variables. I apologize for
> disambiguating toward the worse, rather than better, read. I'm so weary of
> the low-grade litany of "this feature is not something I use or understand,
> and so perl could benefit from its removal." It's so often ill-informed
> that I have become sensitized to it.
>
> I hesitate to say much about the utility of the use of preexisting
> lexicals as the binding target of a for loop. I've never done it on
> purpose…
>

This is a fair reaction - I would have used more precise language were this
the primary topic of the thread :) It's also important to my sentiment
(aimed at whether we should use this as an example for new syntax) that
I've not once heard of anyone using it intentionally on an existing global
variable that's not $_, but as you say, this would have to be a
consideration.

-Dan